Processus sous Linux : ps, top, htop, kill, signaux et nice
On consulte les processus Linux avec ps aux (instantané), top et htop (liste mise à jour avec la charge). On les arrête avec kill PID, qui envoie par défaut un SIGTERM poli ; kill -9 (SIGKILL) n'est nécessaire que si le processus ne réagit pas. La priorité se règle avec nice au lancement et avec renice pour un processus déjà en cours, dans une plage de -20 à 19.
Tout programme en cours d'exécution sous Linux est un processus, doté d'un numéro PID, d'un propriétaire, d'un état et d'une priorité. On consulte les processus avec ps, top et htop, on les arrête avec kill, et on modifie leur priorité avec nice et renice. Voyons comment lire la sortie de ces commandes, quels signaux envoyer et pourquoi kill -9 ne doit pas être le premier réflexe.
Qu'est-ce qu'un processus et qu'est-ce qu'un PID
Un processus est un programme en cours d'exécution : son code, sa mémoire, ses fichiers ouverts et un ensemble d'attributs. Le noyau attribue à chaque processus un identifiant unique, le PID, et retient aussi le PPID, le numéro de son parent qui l'a lancé. Le tout premier processus du système, de PID 1, est en général systemd : il devient l'« ancêtre » de tous les autres.
Un nouveau processus apparaît en deux temps. D'abord le parent appelle fork() et obtient une copie de lui-même, puis la copie appelle execve() et remplace son code par celui du nouveau programme. Quand vous tapez ls dans le terminal, bash fait exactement cela et attend la fin de son enfant avec wait().
$ echo $$ # PID de l'interpréteur courant
4182
$ ps -o pid,ppid,cmd -p $$
PID PPID CMD
4182 4170 -bash
Afficher les processus avec ps
ps prend un instantané : il montre les processus à l'instant où il est lancé, puis s'arrête. Sans arguments, il n'affiche que les processus du terminal courant ; en pratique on utilise donc presque toujours l'une des deux variantes suivantes.
$ ps aux | head -5
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
root 1 0.0 0.3 168540 12780 ? Ss 09:12 0:03 /sbin/init
root 2 0.0 0.0 0 0 ? S 09:12 0:00 [kthreadd]
www-data 1532 1.2 2.1 412308 86420 ? S 09:15 1:47 php-fpm: pool www
postgres 1610 0.4 3.8 221004 154312 ? Ss 09:15 0:31 postgres: checkpointer
Ici a désigne les processus de tous les utilisateurs, u le format détaillé avec le propriétaire, x inclut les processus sans terminal (démons). La syntaxe alternative de style System V, ps -ef, affiche le PPID, pratique pour savoir qui a lancé qui.
| Colonne | Signification |
|---|---|
PID | identifiant du processus |
%CPU, %MEM | part du processeur et de la mémoire physique |
VSZ | mémoire virtuelle en Ko (y compris ce qui n'est pas chargé en RAM) |
RSS | mémoire physique réellement occupée, en Ko |
STAT | état du processus (R, S, D, Z, T) et indicateurs |
TIME | temps processeur cumulé, et non durée d'exécution |
Astuces utiles avec ps
# top 10 par mémoire
ps aux --sort=-%mem | head -11
# top 10 par processeur
ps aux --sort=-%cpu | head -11
# colonnes personnalisées
ps -eo pid,ppid,user,ni,stat,etime,cmd
# arbre des processus
ps -ef --forest
pstree -p
# trouver le PID par nom
pgrep -a nginx
pidof nginx
Erreur classique : chercher un processus avec ps aux | grep nginx et voir dans le résultat la commande grep elle-même. Utilisez pgrep ou l'astuce grep [n]ginx, qui ne correspond pas à sa propre ligne de commande.
États des processus : R, S, D, Z, T
La lettre de la colonne STAT n'est pas anodine : c'est l'état réel du processus. Elle conditionne l'interprétation de la charge et l'efficacité même de kill.
| Code | État | Signification concrète |
|---|---|---|
R | Running | s'exécute ou attend son tour sur le CPU |
S | Interruptible sleep | attend un événement (réseau, saisie, minuterie) ; état habituel de la plupart des processus |
D | Uninterruptible sleep | attend une entrée-sortie dans le noyau, les signaux ne sont pas délivrés |
Z | Zombie | terminé, mais le parent n'a pas récupéré son code de sortie |
T | Stopped | suspendu par le signal SIGSTOP ou par Ctrl+Z |
Les caractères supplémentaires après la lettre sont également utiles : s — leader de session, + — processus au premier plan dans le terminal, < — priorité élevée, N — priorité basse, l — multithreadé.
Processus en état D
Un processus en D se trouve dans un appel système et attend, par exemple, une réponse du disque ou d'un NFS bloqué. Aucun signal ne lui est délivré, pas même SIGKILL. Donc kill -9 ne sert à rien : il faut chercher la cause de l'attente — examiner iostat, dmesg, l'état du stockage réseau.
Processus zombies
Un zombie est déjà mort : il ne consomme ni CPU ni mémoire, il occupe seulement une ligne dans la table des processus. On ne peut pas le tuer, il est déjà terminé. Il disparaît lorsque le parent appelle wait(), ou lorsque le parent lui-même se termine et que le zombie est « adopté » par le PID 1.
# trouver les zombies et leurs parents
ps -eo pid,ppid,stat,cmd | awk '$3 ~ /Z/'
Un zombie isolé est sans danger. S'ils se comptent par centaines et que leur nombre augmente, c'est une erreur dans le programme parent : il faut le corriger ou le redémarrer.
top : processus et charge en temps réel
top affiche la même liste, la met à jour toutes les quelques secondes et fournit un résumé du système. C'est la première commande qu'on lance quand « le serveur ralentit ».
top - 14:21:07 up 12 days, 3:02, 2 users, load average: 1.84, 1.20, 0.95
Tasks: 213 total, 2 running, 211 sleeping, 0 stopped, 0 zombie
%Cpu(s): 23.1 us, 4.2 sy, 0.0 ni, 70.3 id, 1.9 wa, 0.0 hi, 0.5 si, 0.0 st
MiB Mem : 7821.4 total, 412.6 free, 3105.8 used, 4303.0 buff/cache
MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 4398.2 avail Mem
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
1532 www-data 20 0 412308 86420 14212 R 38.2 1.1 1:47.31 php-fpm
1610 postgres 20 0 221004 154312 148900 S 6.0 1.9 0:31.08 postgres
Dans la ligne %Cpu(s), le plus important est : us — code utilisateur, sy — noyau, id — inactivité, wa — attente du disque. Un wa élevé alors que le processeur est libre indique clairement un goulet d'étranglement dans les entrées-sorties.
Raccourcis clavier de top
| Touche | Action |
|---|---|
P / M | tri par CPU / par mémoire |
1 | afficher chaque cœur séparément |
c | ligne de commande complète |
u | filtre par utilisateur |
k | envoyer un signal à un processus |
r | modifier le nice d'un processus |
H | afficher les threads |
q | quitter |
Pour les scripts et les journaux, le mode batch est utile : top -b -n 1 | head -20 affiche un seul instantané sans interaction. Pour suivre un processus précis : top -p 1532.
Load average : une file d'attente, pas un pourcentage
Les trois valeurs de load average sont la longueur moyenne de la file d'attente sur 1, 5 et 15 minutes. Sous Linux, y entrent les processus dans les états R et D, mais pas le sommeil ordinaire S. Il faut comparer le LA au nombre de cœurs (nproc) : sur 4 cœurs, une valeur de 4 correspond à une charge complète, et 12 signifie une file trois fois plus longue que la capacité disponible.
Si le LA est élevé alors que le processeur est inactif, cherchez les processus en D : ps -eo stat,pid,cmd | grep '^D'. Presque toujours, c'est un disque lent ou un stockage réseau.
htop : un remplacement pratique de top
htop affiche la même chose, avec des indicateurs colorés par cœur, le défilement, la prise en charge de la souris et une vue en arbre des processus. Il faut en général l'installer : sudo apt install htop ou sudo dnf install htop.
F3ou/— rechercher un processus par nom ;F4— filtre n'affichant que les correspondances ;F5out— arbre « parent — enfants » ;F6— choix de la colonne de tri ;F7/F8— diminuer ou augmenter le nice ;F9— menu des signaux pour le processus sélectionné ;Space— marquer plusieurs processus pour une action groupée.
Sur des serveurs où l'on ne peut rien installer, top suffit : toutes les opérations clés y sont également disponibles.
Terminer un processus : kill et les signaux
La commande kill ne « tue » pas à proprement parler : elle envoie un signal au processus. La suite dépend du signal et de la façon dont le programme le traite.
| Signal | Numéro | Rôle |
|---|---|---|
SIGHUP | 1 | coupure du terminal ; de nombreux démons relisent leur configuration |
SIGINT | 2 | interruption, équivalent de Ctrl+C |
SIGKILL | 9 | arrêt forcé par le noyau, impossible à intercepter |
SIGTERM | 15 | demande d'arrêt propre ; signal par défaut de kill |
SIGSTOP | 19 | suspension, impossible à intercepter |
SIGCONT | 18 | reprendre un processus suspendu |
SIGTSTP | 20 | suspension depuis le terminal, Ctrl+Z |
Les numéros valent pour x86 et ARM ; la liste complète s'obtient avec kill -l. Indiquer le signal par son nom est plus fiable que par son numéro.
kill 1532 # SIGTERM
kill -TERM 1532 # la même chose, explicitement
kill -HUP $(pidof nginx) # relire la configuration
kill -STOP 1532; kill -CONT 1532
kill -0 1532 && echo "processus vivant"
Le signal 0 n'envoie rien : il vérifie seulement que le processus existe et que vous avez le droit de lui écrire — pratique dans les scripts.
Pourquoi ne pas commencer par kill -9
SIGTERM donne au programme la chance de fermer ses fichiers, de vider ses tampons, de supprimer ses fichiers de verrouillage et de terminer proprement ses transactions. SIGKILL coupe tout instantanément : les données non écrites sont perdues, les fichiers temporaires restent, et une base de données peut passer en récupération au démarrage suivant.
La bonne séquence est la suivante :
- Envoyer
kill PID(SIGTERM). - Attendre 5 à 30 secondes en vérifiant avec
kill -0 PID. - Seulement si le processus est toujours vivant et n'est pas en état
D—kill -9 PID.
Pour les services gérés par systemd, mieux vaut ne pas toucher au PID à la main : systemctl stop envoie lui-même SIGTERM, attend le délai imparti, puis achève avec SIGKILL.
pkill et killall : par nom
pkill -f "python worker.py" # par la ligne de commande complète
pkill -u alice # tous les processus de l'utilisateur
killall -TERM node # tous les processus nommés node
pgrep -l -f worker # vérifiez d'abord ce qui correspond au motif
Avant un pkill massif, lancez toujours pgrep avec le même motif : -f correspond à n'importe quelle partie de la ligne de commande et peut facilement attraper des processus non désirés.
On ne peut envoyer des signaux qu'à ses propres processus ; pour les autres, il faut sudo. L'erreur Operation not permitted signifie justement cela.
Priorité des processus : nice et renice
La valeur nice indique au planificateur quel processus doit céder le processeur. La plage va de -20 (priorité la plus haute) à 19 (cède à tous), la valeur par défaut étant 0. Dans top, elle apparaît dans la colonne NI ; PR est la priorité interne dérivée.
# lancer une tâche lourde avec une priorité basse
nice -n 10 tar czf backup.tar.gz /var/www
# abaisser la priorité d'un processus en cours
renice -n 15 -p 1532
# relever la priorité (root uniquement)
sudo renice -n -5 -p 1610
# tous les processus d'un utilisateur
sudo renice -n 10 -u alice
Un utilisateur ordinaire ne peut que baisser la priorité de ses propres processus ; les valeurs négatives sont réservées à root. Il faut savoir que nice ne concerne que le CPU. Si une tâche ralentit le système par le disque, utilisez ionice -c3 commande — classe idle, qui n'obtient l'accès au disque que lorsque personne d'autre n'en a besoin.
Processus en arrière-plan et tâches du shell
On peut lancer une commande en arrière-plan en ajoutant &, ou la suspendre avec Ctrl+Z. Le shell tient une liste de tâches, gérée par des commandes intégrées.
$ long_task &
[1] 5120
$ jobs
[1]+ Running long_task &
$ fg %1 # ramener au premier plan
^Z # suspendre (SIGTSTP)
$ bg %1 # poursuivre en arrière-plan
À la fermeture du terminal, le shell envoie SIGHUP aux tâches, qui s'arrêtent alors. Pour qu'un processus survive à la sortie, lancez-le avec nohup commande &, détachez-le avec disown ou utilisez tmux. Pour un fonctionnement permanent, le plus juste est de le déclarer comme service systemd.
Scénarios de diagnostic typiques
Qui consomme le processeur
top -o %CPU # ou P à l'intérieur de top
ps -eo pid,user,%cpu,etime,cmd --sort=-%cpu | head
Si un processus consomme du CPU sans raison, commencez par baisser sa priorité avec renice : c'est sans risque et vous laisse le temps d'examiner la situation.
Qui occupe un port
sudo ss -ltnp | grep :8080
sudo lsof -i :8080
La sortie donne le PID ; ensuite, dans /proc/PID/, on trouve le fichier exécutable (exe), le répertoire de travail (cwd) et les arguments (cmdline).
Le processus a disparu sans prévenir
Cause fréquente : l'OOM Killer, qui tue des processus lorsque la mémoire manque. Pour vérifier : dmesg -T | grep -i oom ou journalctl -k | grep -i "killed process".
Conclusion
Pour travailler avec les processus sous Linux, un petit ensemble de commandes suffit : ps aux pour un instantané, top et htop pour observer, kill avec le bon signal pour terminer, et nice/renice pour les priorités. Examinez l'état d'un processus avant d'agir : les zombies et les processus en D ne se soignent pas avec des signaux. Commencez par SIGTERM et réservez kill -9 aux cas extrêmes. Les processus, la mémoire, le load average et les appels système sont détaillés en pratique dans le cours Linux.
Questions fréquentes
En quoi ps aux diffère-t-il de ps -ef ?
Ce sont deux syntaxes de la même commande : aux relève du style BSD avec les colonnes %CPU, %MEM et STAT, -ef du style System V avec la colonne PPID. Dans les deux cas, l'ensemble des processus affichés est le même : tous les processus du système.
Comment savoir combien de processus tournent sur le système ?
Le plus simple est de regarder la ligne Tasks dans top, ou d'exécuter ps -e --no-headers | wc -l. Le nombre de threads s'obtient avec ps -eLf --no-headers | wc -l.
Pourquoi un processus ne s'arrête-t-il pas même après kill -9 ?
Soit il est en état D et attend une entrée-sortie dans le noyau, soit c'est un zombie, déjà terminé. Dans le premier cas, cherchez le problème du disque ou du stockage réseau ; dans le second, corrigez ou redémarrez le parent.
Que se passe-t-il si l'on tue le processus de PID 1 ?
Le noyau protège init : les signaux ordinaires, SIGKILL compris, ne lui sont pas délivrés s'il ne les traite pas lui-même. Si init se terminait malgré tout, le système tomberait en kernel panic.
Comment limiter la mémoire qu'un processus peut utiliser ?
Pour un service systemd, définissez MemoryMax= dans le fichier d'unité ; pour un lancement ponctuel, utilisez systemd-run --scope -p MemoryMax=500M commande. Cela passe par les cgroups et est plus fiable que l'ancienne commande ulimit -v.
Ce sujet est traité en détail avec de la pratique dans le cours « Linux: с нуля до уверенного администрирования ».
Voir le cours