Comprendre et Optimiser ulimit sur Linux

Introduction

L’un des problèmes courants sur les serveurs Linux concerne la gestion des ressources système pour les processus en cours d’exécution. Un serveur en production, qu’il s’agisse d’un serveur Moodle, Apache, PostgreSQL, ou MySQL, peut rencontrer des erreurs du type :

  • « Too many open files » (Trop de fichiers ouverts)
  • « Cannot fork: resource temporarily unavailable » (Impossible de créer un nouveau processus)
  • « Memory allocation failed » (Échec d’allocation mémoire)

Dans la majorité des cas, ces problèmes sont liés à des limitations imposées par ulimit, un outil intégré à Linux permettant de gérer les ressources système allouées aux processus.

Dans cet article, nous allons expliquer en détail ulimit, identifier les problèmes courants et voir comment l’optimiser pour garantir de meilleures performances serveur.


📌 Qu’est-ce que ulimit ?

ulimit (User Limit) est une commande permettant de définir et de gérer les ressources maximales qu’un utilisateur peut utiliser sur un système Linux.

Chaque processus utilisateur est soumis à des limitations pour éviter qu’un seul utilisateur ou service ne monopolise les ressources (exemple : un processus Apache consommant toute la mémoire du serveur).

Il existe deux types de limites :

  1. Soft limit (limite souple) : Valeur par défaut qui peut être augmentée par l’utilisateur jusqu’à la hard limit.
  2. Hard limit (limite stricte) : Valeur maximale qu’un utilisateur peut définir. Elle ne peut être augmentée que par l’administrateur (root).

📌 Commandes ulimit : Comment Vérifier et Modifier les Limites ?

1️⃣ Afficher toutes les limitations

ulimit -a

📊 Exemple de sortie :

real-time non-blocking time  (microseconds, -R) unlimited
core file size              (blocks, -c) 0
data seg size               (kbytes, -d) unlimited
file size                   (blocks, -f) unlimited
open files                          (-n) 1024
max user processes                  (-u) 4096
stack size                  (kbytes, -s) 8192
cpu time                   (seconds, -t) unlimited
virtual memory              (kbytes, -v) unlimited

📌 Les valeurs importantes à surveiller :

OptionSignificationProblèmes potentiels
-nNombre maximum de fichiers ouvertsPeut provoquer des erreurs « Too many open files » sur un serveur web ou une base de données.
-uNombre maximal de processus utilisateurSi trop bas, risque de « resource temporarily unavailable » si trop de connexions simultanées.
-sTaille de la pile mémoireTrop faible ? Risque d’erreurs de segmentation pour certains logiciels comme PostgreSQL.
-vMémoire virtuelle maximalePeut limiter la RAM disponible pour un processus gourmand.

📌 Recommandations des Valeurs ulimit par Type de Serveur

Le tableau ci-dessous fournit des recommandations optimisées pour différents types de serveurs Linux.

Type de Serveuropen files (-n)max user processes (-u)stack size (-s) (kB)max memory (-m)max locked memory (-l) (kB)
Serveur Web (Apache/Nginx)6553512800016384unlimited4096
Serveur Base de Données (MySQL/PostgreSQL)10000025600032768unlimited8192
Serveur d’Application (Moodle, ERP, etc.)6553512800016384unlimited4096
Serveur de Virtualisation (KVM, Docker)10000025600032768unlimited8192
Serveur Big Data (Hadoop, Spark)20000051200065536unlimited16384
Serveur IA/Machine Learning20000051200065536unlimited32768

📌 Modifier les Limites de Manière Permanente

Pour éviter que les changements ne disparaissent après un redémarrage, il faut modifier trois fichiers principaux :

1️⃣ /etc/security/limits.conf (Pour les sessions utilisateur)

Ajoutez ces lignes à la fin du fichier :

*          soft    nofile    65535
*          hard    nofile    524288
*          soft    nproc     128000
*          hard    nproc     256000
root       soft    nofile    65535
root       hard    nofile    524288

2️⃣ /etc/systemd/system.conf (Pour les services systemd)

Ajoutez ces lignes :

DefaultLimitNOFILE=65535:524288
DefaultLimitNPROC=128000:256000
DefaultLimitSTACK=16384:32768

3️⃣ /etc/systemd/user.conf (Pour les processus utilisateur sous systemd)

Ajoutez :

DefaultLimitNOFILE=65535:524288
DefaultLimitNPROC=128000:256000

📌 Explication de la syntaxe 65535:524288 :

  • 65535 = Soft limit (valeur par défaut pouvant être augmentée)
  • 524288 = Hard limit (valeur maximale absolue)

4️⃣ Appliquer les modifications

Rechargez systemd :

sudo systemctl daemon-reexec

Et redémarrez le serveur :

sudo reboot

📌 Vérification Après Modification

Une fois le serveur redémarré, vérifiez que les nouvelles limites sont bien appliquées :

ulimit -a

Vérifier pour un service spécifique (ex : Apache) :

cat /proc/$(pgrep -u www-data apache2 | head -n 1)/limits

Pour vérifier les valeurs ulimit appliquées à chaque type de serveur (serveur web, base de données, applications, etc.), voici les commandes spécifiques à exécuter en fonction du type de service en cours d’exécution.


📌 Vérification ulimit par Type de Serveur

🖥️ Serveur Web (Apache/Nginx)

💡 Utilisateurs concernés : www-data (Debian/Ubuntu) ou apache (CentOS/RHEL)
🔍 Commandes :

cat /proc/$(pgrep -u www-data apache2 | head -n 1)/limits   # Pour Apache
cat /proc/$(pgrep -u www-data nginx | head -n 1)/limits    # Pour Nginx

Si les valeurs sont trop basses (ex. open files (-n) = 1024), alors il faut les augmenter.


🗄️ Serveur Base de Données (MySQL/PostgreSQL)

💡 Utilisateurs concernés : mysql pour MySQL/MariaDB, postgres pour PostgreSQL
🔍 Commandes :

cat /proc/$(pgrep -u mysql mysqld | head -n 1)/limits       # Pour MySQL/MariaDB
cat /proc/$(pgrep -u postgres postgres | head -n 1)/limits  # Pour PostgreSQL

📌 Problème courant : "Too many open files" → Si open files (-n) est trop bas, les requêtes SQL peuvent échouer.


📦 Serveur d’Application (Moodle, ERP, etc.)

💡 Utilisateur variable selon l’application
🔍 Commandes :

cat /proc/$(pgrep -u www-data php-fpm | head -n 1)/limits  # Pour PHP-FPM (Moodle)
cat /proc/$(pgrep -u tomcat tomcat | head -n 1)/limits    # Pour Tomcat (Java)

📌 Problème courant : max user processes (-u) trop bas → Erreur "Cannot fork".


☁️ Serveur de Virtualisation (Docker, KVM)

💡 Utilisateurs : root ou libvirt-qemu pour KVM
🔍 Commandes :

cat /proc/$(pgrep -u root dockerd | head -n 1)/limits     # Pour Docker
cat /proc/$(pgrep -u libvirt-qemu qemu | head -n 1)/limits  # Pour KVM

📌 Problème courant : max memory (-m) limité → Peut empêcher le lancement de nouvelles VM.


📊 Serveur Big Data (Hadoop, Spark)

💡 Utilisateur variable selon la distribution
🔍 Commandes :

cat /proc/$(pgrep -u hadoop java | head -n 1)/limits   # Pour Hadoop
cat /proc/$(pgrep -u spark java | head -n 1)/limits    # Pour Spark

📌 Problème courant : stack size (-s) trop bas → Peut provoquer des erreurs de segmentation sur Spark.


🤖 Serveur IA/Machine Learning (TensorFlow, PyTorch)

💡 Utilisateur : souvent root ou un utilisateur dédié
🔍 Commandes :

cat /proc/$(pgrep -u root python | head -n 1)/limits   # Pour un script Python utilisant TensorFlow/PyTorch

📌 Problème courant : max locked memory (-l) limité → Peut causer des erreurs CUDA sur GPU.


📌 Vérifier les Limites Système Globales

Si vous voulez vérifier les limites configurées pour tous les services et utilisateurs :

🔍 Afficher les limites générales (ulimit -a)

ulimit -a

🔍 Afficher les limites systemd (systemctl show)

systemctl show --property=DefaultLimitNOFILE
systemctl show --property=DefaultLimitNPROC

🔍 Afficher les valeurs définies dans systemd

grep -E "DefaultLimitNOFILE|DefaultLimitNPROC" /etc/systemd/system.conf

Oui, tu peux modifier les limites ulimit directement sur les processus existants, sans redémarrer le serveur ni les services. Voici comment faire :


📌 Modifier ulimit en Direct sur un Processus en Cours

1️⃣ Vérifier les limites actuelles d’un processus

Pour voir les limites appliquées à un processus spécifique (ex : Apache ou PostgreSQL), utilise :

cat /proc/$(pgrep -u www-data apache2 | head -n 1)/limits
cat /proc/$(pgrep -u postgres postgres | head -n 1)/limits

Si la valeur Max open files est trop basse, elle peut être modifiée sans redémarrer.


2️⃣ Changer ulimit sur un processus en cours avec prlimit

La commande prlimit permet de modifier directement les limites d’un processus déjà en exécution.

✅ Exemple : Modifier Max Open Files pour Apache

sudo prlimit --pid $(pgrep -u www-data apache2 | head -n 1) --nofile=65535:524288

✔️ Cela mettra immédiatement 65535 en soft limit et 524288 en hard limit.

✅ Exemple : Modifier Max Open Files pour PostgreSQL

sudo prlimit --pid $(pgrep -u postgres postgres | head -n 1) --nofile=100000:524288

3️⃣ Vérifier que les nouvelles valeurs sont bien appliquées

cat /proc/$(pgrep -u www-data apache2 | head -n 1)/limits
cat /proc/$(pgrep -u postgres postgres | head -n 1)/limits

Si Max open files est bien à 65535 (ou 100000 pour PostgreSQL), la modification est effective.


📌 Modifier d’autres paramètres sans redémarrer

Voici d’autres exemples de changements en temps réel :

ParamètreCommande prlimit
Modifier nofile (fichiers ouverts)sudo prlimit --pid <PID> --nofile=65535:524288
Modifier nproc (processus max)sudo prlimit --pid <PID> --nproc=128000:256000
Modifier stack (taille de pile)sudo prlimit --pid <PID> --stack=16384:32768

📌 Remplace <PID> par l’ID du processus concerné, que tu peux obtenir avec :

pgrep -u www-data apache2
pgrep -u postgres postgres

🚀 Conclusion

ulimit est un outil essentiel pour gérer les ressources système sur un serveur Linux. Une mauvaise configuration peut entraîner des erreurs critiques et ralentir les performances du serveur.

🔹 Problèmes courants :

  • « Too many open files » 📂 → Augmenter ulimit -n
  • « Cannot fork » ❌ → Augmenter ulimit -u
  • « Out of memory » 💾 → Vérifier ulimit -m et -v

🔹 Optimisation recommandée pour un serveur de production :

ulimit -n 65535
ulimit -u 128000
ulimit -m unlimited

En appliquant ces optimisations, vous améliorez la stabilité et la performance de votre serveur ! 🚀