Ulimit
Les différents paramètres
J’ai parlé ci-dessus de CPU et de RAM, cependant ulimit permet de définir bien d’autres limites que celle-ci. D’ailleurs, on entend souvent parler de la limite des max open files qui nécessite d’être augmentée pour le bon fonctionnement de certains logiciels (mongoDB par exemple). Sans surprise, la commande qui vous permet de controller tout ça s’appelle ulimit. L’option -a permet d’afficher les réglages pour l’utilisateur courant.
Buzut$ ulimit -a core file size (blocks, -c) 0 data seg size (kbytes, -d) unlimited scheduling priority (-e) 0 file size (blocks, -f) unlimited pending signals (-i) 15584 max locked memory (kbytes, -l) 64 max memory size (kbytes, -m) unlimited open files (-n) 1024 pipe size (512 bytes, -p) 8 POSIX message queues (bytes, -q) 819200 real-time priority (-r) 0 stack size (kbytes, -s) 8192 cpu time (seconds, -t) unlimited max user processes (-u) 15584 virtual memory (kbytes, -v) unlimited file locks (-x) unlimited
Il s’agit ci-dessus des réglages par défaut d’une Ubuntu 14.04. Voyons dans le détail les implications de ces différents paramètres.
- core file size:
Nombre maximum de core dumps. Il s’agit d’un snapshot du système comprenant l’état de la RAM, le context switch et les registres processeur. C’est à utiliser à des fins de debugging seulement et vous n’en avez habituellement pas besoin. À laissez à 0 donc, au risque de rapidement saturer votre espace disque.
- data seg size:
Taille maximum du segment de données d’un programme. Il s’agit d’une portion d’espace d’adressage virtuel d’un programme contenant les différentes variables de ce dernier.
- scheduling priority:
Priorité maximum que l’on peut attribuer à un processus. La gestion des priorités, ou ordonnancement, définit les processus l’ordre dans lequel les processus auront accès au processeur (utile lorsqu’on a besoin de faire plusieurs tâches à la fois).
- file size:
Taille maximum des fichiers écrit par le shell et ses processus enfants.
- pending signal:
Un poil complexe, on spécifie ici la limite du nombre de signaux qui peuvent être en attente pour un process donné (tels que sigterm, sigkill, sigstop…) lorsque ce dernier est en attente d’I/O. Lorsqu’un process est dans cet état, il n’est pas possible de l’interrompre (le kernet attend que le process « se réveille »), c’est pour cela qu’il y a une file d’attente. Le man de sigpending vous en apprendra plus au besoin.
- max locked memory:
Taille maximum de mémoire qu’un processus peut « verrouiller » en RAM afin de prévenir que ce dernier ne swap.
- max memory size:
Taille maximale qu’un processus peut occuper en RAM (Appelé resident set size. À ne pas confondre avec la taille totale de mémoire virtuelle que le processus possède.
- open files:
Nombre de descripteur de fichier qui peuvent être ouvert concurremment.
- POSIX message queues:
Nombre maximum (en bytes) dans la file d’attente de message POSIX. N’hésitez pas à consulter le man de la message queue pour plus de détails.
- real-time priority:
C’est la priorité maximale pour un processus, telle qu’il ne peut être interrompu (c’est pour cela qu’on l’appelle real time).
- stack size:
Taille maximum de la stack size. Il s’agit d’une région réservée en mémoire (à ne pas confondre avec la heap memory) utilisée pour stocker l’emplacement des appels à fonction. Cependant, le développeur peut choisir d’y stocker d’autres informations.
- cpu time:
Temps processeur maximum en secondes.
- max user processes:
Il s’agit du nombre maximal de processus qu’un utilisateur peut démarrer ou forker.
- virtual memory:
Taille maximale de mémoire virtuelle disponible pour un utilisateur donné. Il s’agir de la somme de la mémoire physique et de la mémoire de masse (les disques dur).
- file locks:
Nombre maximum de de fichiers qu’un processus peut verrouiller. Le file locking est un mécanisme permettant de restreindre l’accès d’un fichier à seulement un utilisateur ou processus à un instant donné.
Poser un diagnostic
Il est bien souvent délicat de savoir exactement dans quelle mesure on utilise les ressources. Bien sur, top peut nous donner une idée. Cela dit, le plupart du temps, nous avons à faire à des questions de file descriptors ou de nombre de processus. Je vous explique donc comment mesurer ce que vous utilisez. commençons par le plus facile : le nombre de processus. Il s’agit d’un petit one-liner :
# ps h -Led -o user | sort | uniq -c | sort -n
1 Debian-exim
1 messagebus
1 ntpd
4 syslog
5 newrelic
14 www-data
34 gogs
34 mysql
94 root
On voit donc l’ensemble de nos utilisateurs et le nombre de processus que chacun d’entre eux a lancé. Easy ! Maintenant, les file descriptor, un peu plus long. Mais ne vous en faites pas, ce n’est pas non plus insurmontable. Nous avons vu dans la commande précédente que mysql utilise 34 processus. Nous allons trouver combien cet utilisateur possède de file descriptors. Premièrement, on trouve son pid à l’aide la commande ps :
# ps aux | grep mysql root 853 0.0 0.0 18148 756 ? S Apr15 0:00 /bin/bash /usr/bin/mysqld_safe mysql 1085 0.5 20.4 941668 412232 ? Sl Apr15 220:17 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --plugin-dir=/usr/lib/mysql/plugin --user=mysql --skip-log-error --pid-file=/var/run/mysqld/mysqld.pid --socket=/var/run/mysqld/mysqld.sock --port=3306
L’utilisateur mysql possède le pid 1085. On va maintenant compter le nombre d’open files grace à la commande lsof :
# lsof -p 1085 | wc -l 410
Voilà, on sait que notre mysql possède 410 file descriptors ouverts.
Modifier la configuration
Il est grand temps de tuner ces réglages. Vous avez du remarquer en faisant ulimit -a qu’à chaque ligne correspondait une lettre. En fait, vous pouvez l’utiliser pour modifier dynamiquement la configuration. Par exemple, si je veux augmenter le nombre d’open files (n), à 64 000, il me suffit d’utiliser la commande ulimit -n 64000. Cette manière présente tout de même quelques limites… La première : elle n’est valable que dans le shell courant ; la seconde : elle ne survit pas à un redémarrage. Pour configurer les limites de manière persistante et pour différents utilisateurs, il va falloir se diriger vers un – ou plutôt plusieurs – fichiers de conf. Le premier fichier, /etc/security/limits.conf, contient beaucoup de choses, mais c’est surtout la fin qui nous intéresse :
#* soft core 0 #root hard core 100000 #* hard rss 10000 #@student hard nproc 20 #@faculty soft nproc 20 #@faculty hard nproc 50 #ftp hard nproc 0 #ftp - chroot /ftp #@student - maxlogins 4 # je rajoute ici une limite à 64k pour les file descriptors pour l'utilisateur mongod (soft et hard) mongod soft nofile 64000 mongod hard nofile 64000
Comme vous le voyez dans l’exemple, vous pouvez désigner tous les utilisateurs avec une wildcard. Par ailleurs, je parle ici de limites soft et hard. La différence est que la limite soft peut être modifiée à la hausse par l’utilisateur ou le processus, tandis qu’il ne pourra pas dépasser la limite hard. Le soft est une valeur par défaut en quelque sorte. Ici je fixe la même valeur pour au deux, ce qui signifie que Mongo aura par défaut 64 000 file descriptors et qu’il ne pourra aller au delà. Enfin, vous devrez également modifier deux fichiers :
- /etc/pam.d/common-session
- /etc/pam.d/common-session-noninteractive
Il vous faudra ajouter à chacun d’entre eux la ligne suivante :
session required pam_limits.so
