Processus : observer, cibler, arrêter, contraindre
Référence d'exploitation des processus sous Linux : lire l'état du système (ps, top, uptime, /proc), retrouver le bon PID avant d'agir, arrêter avec la bonne commande de la famille kill, régler priorité et limites, diagnostiquer une charge, une fuite de mémoire ou un processus qu...
Référence d’exploitation des processus sous Linux : lire l’état du système (ps, top, uptime, /proc), retrouver le bon PID avant d’agir, arrêter avec la bonne commande de la famille kill, régler priorité et limites, diagnostiquer une charge, une fuite de mémoire ou un processus qui refuse de mourir. La sémantique des signaux et des codes de sortie est dans le runbook signaux ; les services et leur init dans le runbook artix-init.
Choisir le bon outil
Intention Outil Pourquoi
────────────────────────────── ────────────── ────────────────────
Instantané scriptable ps sortie stable,
colonnes choisies
Vue temps réel, tri interactif top présent partout
Vue confortable, arborescence htop, btop si installés
Arbre des filiations pstree -p voit qui a lancé quoi
Retrouver un PID pgrep sans grep parasite
Agir sur plusieurs processus pkill, killall sélection par motif
Qui tient ce fichier, ce port lsof, fuser la question inverse
Ce que fait un processus bloqué strace, /proc dernier recours
Charge dans la durée uptime, vmstat tendance, pas
instantané
En une phrase : ps pour scripter, top pour regarder, pgrep pour cibler,
pkill pour agir, lsof pour la question inverse.
Principes fondamentaux
Un processus est un arbre, pas une liste. Chaque processus a un parent, et tuer un parent ne tue pas nécessairement ses enfants : ils sont adoptés par l’init. C’est pourquoi arrêter un service par son PID principal laisse parfois des travailleurs orphelins qui continuent d’écrire.
init (PID 1)
└─ shell de session
└─ tmux
└─ shell
└─ commande ← Ctrl-C vise le GROUPE au premier
└─ enfant plan, pas ce seul processus
L’état d’un processus dit ce qui est possible. La colonne
STATdepsest le premier diagnostic, avant toute action.
Lettre État Conséquence pratique
────── ───────────────────── ──────────────────────────────────
R en cours ou prêt consomme du processeur
S en attente interruptible normal, la plupart des processus
D attente NON interruptible aucun signal ne passe, KILL compris
Z zombie déjà mort, attend son parent
T arrêté (Ctrl-Z) reprend avec SIGCONT ou fg
< N priorité relevée, abaissée voir nice
s + chef de session, premier plan
La charge moyenne n’est pas un pourcentage. C’est un nombre de tâches prêtes ou en attente disque, à comparer au nombre de cœurs. Une charge de 4 sur 8 cœurs est confortable, la même sur 2 cœurs est saturée. Une charge élevée avec un processeur inoccupé désigne le disque ou le réseau.
La mémoire « libre » n’est pas la mémoire disponible. Le noyau emploie la mémoire inutilisée comme cache et la rend à la demande. La colonne à lire est
available, jamaisfree. Un système sain a peu de mémoire libre.
Tuer est un dernier recours, cibler est le vrai travail. L’erreur coûteuse n’est pas de choisir le mauvais signal, c’est de viser le mauvais processus. D’où la règle : sélectionner, vérifier la sélection, puis seulement agir.
Opérations standard
Observer l’état du système
uptime # charge 1, 5, 15 minutes
nproc # cœurs, pour interpréter la charge
free -h # mémoire : lire « available »
vmstat 1 5 # tendance : cinq mesures d'une seconde
ps aux --sort=-%cpu | head # instantané des gros consommateurs
ps aux --sort=-%mem | head
top # temps réel ; P trie par CPU, M par mémoire
top -o %MEM -b -n1 | head -15 # même chose, non interactif, scriptable
État attendu : une charge inférieure au nombre de cœurs, et une valeur
available confortable. Dans top, une part élevée de wa signale une attente
disque, pas un manque de processeur.
Choisir ce que ps affiche
ps -eo pid,ppid,user,stat,pcpu,pmem,etime,comm --sort=-pcpu | head
ps -eo pid,ppid,rss,args --sort=-rss | head # mémoire résidente réelle
ps -p 1234 -o pid,ppid,stat,wchan,lstart,args # tout sur un processus
ps -eLf | head # threads compris
pstree -ps 1234 # ascendance et descendance
ps aux est une habitude, ps -eo est un outil : il rend exactement les
colonnes voulues, dans un ordre stable, ce qui le rend utilisable en pipeline.
Retrouver le bon PID avant d’agir
pgrep -a nginx # PID et ligne de commande complète
pgrep -u "$USER" -a python # restreint à un utilisateur
pgrep -f 'monservice --worker' # motif sur la LIGNE COMPLÈTE
pgrep -n firefox # le plus récent
pgrep -c chrome # combien
pidof nginx # équivalent simple, nom exact
État attendu : la liste des PID visés, avec leur ligne de commande, avant toute
action destructrice. pgrep -f puis pkill -f avec le même motif : la
vérification et l’action emploient la même sélection, c’est la seule discipline
qui évite de tuer le mauvais processus.
L’ancienne forme ps aux | grep motif a 2 défauts : elle liste son propre
grep, et son motif attrape des lignes sans rapport. pgrep n’a ni l’un ni
l’autre.
Arrêter : la famille kill
kill 1234 # SIGTERM au PID 1234, forme par défaut
kill -TERM 1234 # identique, explicite
kill -KILL 1234 # dernier recours, aucun nettoyage
kill -0 1234 # ne tue rien : le PID existe-t-il encore
kill -TERM -1234 # tout le GROUPE (noter le tiret)
kill %1 # une tâche du shell courant
pkill nginx # par nom, tous les correspondants
pkill -u autreuser -f 'motif' # par utilisateur ET par ligne complète
pkill -TERM -f 'motif' ; sleep 5 ; pkill -KILL -f 'motif'
killall nginx # par nom EXACT d'exécutable
killall -i nginx # avec confirmation pour chacun
Séquence recommandée, avec fenêtre de politesse :
pgrep -f 'motif' -a # 1. vérifier la sélection
pkill -TERM -f 'motif' # 2. demander l'arrêt
sleep 5
pgrep -f 'motif' -a # 3. contrôler
pkill -KILL -f 'motif' # 4. forcer seulement si nécessaire
Différence à connaître : killall compare le nom de l’exécutable, pkill
compare un motif, et pkill -f compare la ligne de commande entière. Un
pkill python tue tous les scripts Python de la machine ; pkill -f 'python /opt/monapp/serveur.py' vise le bon.
La sémantique de chaque signal, les codes 137 et 143, trap et le nettoyage
sont dans le runbook signaux et codes de sortie.
Contraindre : priorité, mémoire, temps
nice -n 19 commande # lancer à priorité basse (19 = la plus basse)
renice -n 10 -p 1234 # changer après coup
ionice -c3 -p 1234 # priorité disque « au ralenti »
timeout 30s commande # tuer après 30 secondes
timeout -s KILL 30s commande # avec KILL plutôt que TERM
systemd-run --scope -p MemoryMax=1G commande # plafond mémoire, si systemd
ulimit -v 2000000 # limite d'espace virtuel, shell courant
État attendu : la commande s’exécute plus lentement mais laisse la machine
réactive. nice n’améliore jamais les performances de la commande, il protège
le reste du système : c’est un outil de courtoisie, pas d’accélération.
Seul root peut abaisser une valeur de politesse, donc relever une priorité :
renice -n -5 échoue pour un utilisateur ordinaire, ce qui est voulu.
Répondre à la question inverse
lsof -p 1234 # tout ce qu'un processus a ouvert
lsof /var/log/monfichier # qui tient ce fichier
lsof +D /mnt/disque # qui tient quoi sous ce répertoire
lsof -i :8080 # qui écoute ce port
fuser -v /mnt/disque # même question, sortie compacte
fuser -k /mnt/disque # ET tuer ces processus, à manier avec soin
ss -tulpn # ports en écoute, avec les processus
État attendu : la liste des processus concernés. C’est la commande qui débloque un démontage impossible, un port déjà pris, ou un espace disque qui ne revient pas après suppression.
Lire un processus par /proc
ls -l /proc/1234/exe # le binaire réel, même supprimé
ls -l /proc/1234/cwd # son répertoire de travail
tr '\0' '\n' < /proc/1234/cmdline # sa ligne de commande exacte
tr '\0' '\n' < /proc/1234/environ # son environnement, tel qu'hérité
cat /proc/1234/status | head -20 # état, mémoire, threads, UID
ls -l /proc/1234/fd | head # ses descripteurs ouverts
cat /proc/1234/wchan; echo # dans quel appel noyau il attend
C’est la source de vérité : quand un outil et /proc divergent, /proc a
raison. L’environnement hérité y est particulièrement utile pour comprendre un
service qui se comporte autrement qu’en interactif.
Tâches du shell
commande & # arrière-plan
jobs -l # tâches du shell courant, avec PID
fg %1 # ramener au premier plan
bg %1 # reprendre en arrière-plan
Ctrl-Z # suspendre la tâche du premier plan
wait %1 # attendre la fin, et lire son code
Les tâches appartiennent au shell : un autre terminal ne les voit pas dans
jobs, seulement dans ps. Pour qu’un travail survive à la fermeture, voir
nohup, disown et setsid dans le runbook signaux.
Traitement par lots
# Arrêter proprement une famille de processus, puis forcer les récalcitrants
pkill -TERM -f 'monservice --worker'
sleep 5
pgrep -f 'monservice --worker' | while read -r p; do
printf 'récalcitrant: %s\n' "$p"; kill -KILL "$p"
done
# Consommation mémoire cumulée par nom de programme
ps -eo rss,comm --no-headers |
awk '{m[$2]+=$1} END {for (k in m) printf "%8d Ko %s\n", m[k], k}' |
sort -rn | head
# Surveiller un processus jusqu'à sa fin, sans boucle d'attente active
while kill -0 "$pid" 2>/dev/null; do sleep 2; done
printf 'terminé\n'
# Relancer chaque processus d'un utilisateur avec une priorité plus basse
for p in $(pgrep -u "$USER" ffmpeg); do renice -n 15 -p "$p"; done
Dépannage par symptôme
Le système est lent, la charge est élevée
Distinguer processeur, disque et mémoire avant d’agir :
uptime ; nproc # charge rapportée aux cœurs
top -b -n1 | head -5 # ligne %Cpu : us, sy, wa, id
free -h # available, et si l'échange est actif
vmstat 1 5 # colonnes si et so : échange en cours
Constat Conclusion
───────────────────────── ────────────────────────────────────
%us élevé calcul : trouver le processus, nice
%wa élevé attente disque : iotop, ionice
%sy élevé appels système : strace, pilote
si/so non nuls échange actif : mémoire insuffisante
charge élevée, tout inoccupé processus en état D, disque ou réseau
Un processus refuse de mourir
ps -o pid,stat,wchan,comm -p "$pid"
État D : attente non interruptible, aucun signal ne passe, KILL compris.
Traiter la cause, disque en panne ou montage réseau perdu, pas le processus.
État Z : ce n’est plus un processus, il attend que son parent lise son code de
sortie ; agir sur le parent.
La mémoire disparaît
ps -eo pid,rss,comm --sort=-rss | head
grep -E 'MemAvailable|SwapFree' /proc/meminfo
sudo dmesg -T | grep -i 'out of memory' | tail
Un processus tué avec le code 137 sans intervention humaine désigne presque toujours le tueur de mémoire du noyau. Le journal du noyau nomme la victime et le déclencheur.
« Too many open files »
ulimit -Sn ; ulimit -Hn # limites du shell courant
ls /proc/"$pid"/fd | wc -l # ce que le processus a ouvert
cat /proc/"$pid"/limits | grep 'open files' # ses limites réelles
La limite s’hérite du processus qui a lancé le service : la changer dans le shell ne change rien à un service déjà démarré. Corriger dans l’unité ou dans le script de démarrage, puis relancer.
Un démontage est refusé, « target is busy »
lsof +D /mnt/disque | head
fuser -vm /mnt/disque
Un simple shell dont le répertoire courant est sous le point de montage suffit à
bloquer. fuser -k tue les responsables, à n’employer qu’après avoir lu la
liste.
Un port est déjà pris
ss -tulpn | grep :8080
lsof -i :8080
ps aux | grep renvoie une ligne de trop
Le grep se voit lui-même. Employer pgrep -a, ou l’astuce classique
grep '[n]ginx', dont le motif ne correspond pas à sa propre ligne.
Un processus consomme le processeur sans rien faire d’utile
sudo strace -c -p "$pid" # profil des appels système, Ctrl-C pour finir
cat /proc/"$pid"/wchan; echo # où il attend dans le noyau
sudo perf top -p "$pid" # si perf est installé
Problèmes connus et contournements
Tuer un parent n’arrête pas ses enfants
Comportement structurel : les enfants sont réadoptés par l’init et continuent.
Viser le groupe de processus, kill -TERM -PID, ou employer le gestionnaire de
services qui connaît l’arborescence complète.
killall n’a pas le même sens partout
Sur Linux, il tue les processus dont le nom correspond. Sur certains Unix
historiques, il tue tous les processus de l’utilisateur. Dans un script destiné
à durer, préférer pkill avec un motif explicite.
nice n’accélère rien
Il abaisse la priorité d’une tâche pour préserver les autres. Sur une machine inoccupée, il ne change rien du tout. Seul root peut relever une priorité, opération irréversible pour un utilisateur ordinaire.
La colonne mémoire de ps compte 2 fois
RSS inclut les pages partagées entre processus : additionner les RSS d’une
famille de processus surestime la consommation réelle. Pour une mesure honnête,
lire PSS dans /proc/PID/smaps_rollup.
Les limites ne s’appliquent qu’aux processus lancés ensuite
ulimit modifie le shell courant et ce qu’il lancera. Un service déjà démarré
garde les limites héritées à son démarrage, visibles dans /proc/PID/limits.
Pipelines utiles
# Les dix processus les plus gourmands en mémoire, en unités lisibles
ps -eo rss,pid,comm --no-headers --sort=-rss | head -10 |
numfmt --from-unit=1024 --to=iec --field=1
# Consommation cumulée par utilisateur
ps -eo user,rss --no-headers |
awk '{m[$1]+=$2} END {for (u in m) printf "%10d Ko %s\n", m[u], u}' |
sort -rn
# Processus démarrés depuis moins de dix minutes
ps -eo etimes,pid,args --no-headers --sort=etimes |
awk '$1 < 600 {print}' | head
# Tous les processus en état D ou Z, ceux qui demandent une décision
ps -eo pid,stat,wchan,comm --no-headers | awk '$2 ~ /^[DZ]/'
# Nombre de descripteurs ouverts par processus, du plus gourmand au moins
for d in /proc/[0-9]*/fd; do
printf '%s %s\n' "$(ls "$d" 2>/dev/null | wc -l)" "${d%/fd}"
done | sort -rn | head
Voir aussi
Ce qu’un processus rend en s’arrêtant, et la traduction d’un code supérieur à 128 en nom de signal, sont traités dans le runbook signaux-codes-sortie.
Sources amont
Source Nature Relevé le
───────────────────────────────────────────── ───────── ──────────
gitlab.com/procps-ng/procps, notes de version primaire 2026-09-03
man 1 ps, man 1 top, man 1 pgrep primaire 2026-09-03
man 5 proc, documentation du noyau primaire 2026-09-03
man 1 lsof, man 1 fuser primaire 2026-09-03
Ce qui bouge : les colonnes disponibles dans ps -o, les champs de /proc
ajoutés par le noyau, et la bascule complète vers les cgroups v2 qui change les
outils de mesure applicables.
Points clés à retenir
Cibler avant d’agir : pgrep -a avec le motif exact, puis pkill avec le même
motif. L’erreur coûteuse est de viser le mauvais processus, pas de choisir le
mauvais signal.
pkill python tue tous les scripts Python de la machine ; pkill -f sur la
ligne complète vise le bon.
TERM, fenêtre de 5 secondes, contrôle, puis KILL seulement si nécessaire.
La colonne STAT décide : D ne se tue pas, Z se traite par le parent, T
se reprend avec fg ou SIGCONT.
Comparer la charge au nombre de cœurs, et lire available plutôt que free.
lsof et fuser répondent à la question inverse : qui tient ce fichier, ce
point de montage, ce port.
/proc/PID/ est la source de vérité, environnement hérité compris, quand un
outil et le noyau divergent.
nice protège le reste du système, il n’accélère jamais la tâche visée.