08 - Les processus : comprendre ce qui tourne sur ta machine
Ce que tu vas apprendre
- Lister et analyser les processus avec ps, top et htop
- Envoyer des signaux avec kill et comprendre les principaux signaux
- Gerer les jobs en arriere-plan avec fg, bg, nohup et disown
- Comprendre les processus zombies et le rôle de PID 1 (utile pour Docker)
Prerequisites
Avoir suivi les articles précédents de la serie, notamment grep et find. Un terminal Linux ou WSL ouvert.
Quand ton serveur Node rame et que tu ne sais pas pourquoi, quand un processus refuse de mourir, quand ton conteneur Docker se comporte bizarrement au shutdown... a chaque fois, ca revient aux processus. C'est un sujet que beaucoup de devs survolent, et qui finit par leur exploser a la figure en prod.
Lister les processus avec ps
La commande ps affiche un instantane des processus. Seule, elle ne montre que les processus de ton terminal courant. Pour voir tout ce qui tourne :
bash# Tous les processus, format BSD (le plus courant)
ps aux
# Tous les processus, format POSIX
ps -ef
# Filtrer un processus precis
ps aux | grep node
# Astuce : eviter que grep se trouve lui-meme dans les resultats
ps aux | grep '[n]ode'
La sortie de ps aux contient des colonnes utiles. USER te dit qui a lance le processus. PID est l'identifiant unique. %CPU et %MEM montrent la consommation. STAT indique l'état (R = running, S = sleeping, Z = zombie). COMMAND montre la commande complète.
bash# Voir l'arborescence des processus (qui est parent de qui)
ps auxf
# Afficher uniquement certaines colonnes
ps -eo pid,ppid,user,%cpu,%mem,cmd --sort=-%cpu | head -20
Surveiller en temps réel avec top et htop
ps te donne une photo. top te donne une video :
bash# Lancer top
top
# Dans top : appuie sur 'P' pour trier par CPU, 'M' par memoire, 'q' pour quitter
Mais franchement, top est austere. Installe htop et ne regarde plus en arriere :
bashsudo apt install htop
htop
Sur paltemps.fr, quand je debugge un problème de performance, c'est toujours htop que j'ouvre en premier. L'interface est en couleur, tu peux trier, filtrer, et tuer des processus directement avec F9.
Les signaux : parler aux processus
Quand tu fais kill, tu envoies un signal. Et non, kill ne "tue" pas forcement -- ca depend du signal :
bash# Envoyer SIGTERM (signal 15) -- demande polie d'arret
kill 1234
# Equivalent explicite
kill -SIGTERM 1234
kill -15 1234
# SIGKILL (signal 9) -- arret force, le processus ne peut pas l'intercepter
kill -9 1234
kill -SIGKILL 1234
# SIGHUP (signal 1) -- historiquement "terminal ferme"
# Beaucoup de serveurs le reinterpretent comme "recharge ta config"
kill -HUP 1234
# SIGINT (signal 2) -- c'est ce que fait Ctrl+C
kill -INT 1234
La différence entre SIGTERM et SIGKILL est fondamentale. SIGTERM dit au processus "arrêté-toi proprement". Le processus peut intercepter ce signal, fermer ses connexions, sauvegarder son état. SIGKILL ne laisse aucune chance : le kernel arrêté le processus immédiatement. Utilise toujours SIGTERM d'abord. SIGKILL, c'est le dernier recours.
bash# Tuer tous les processus d'un nom
killall node
# pkill permet des patterns
pkill -f "node server.js"
Jobs : foreground et background
Quand tu lances une commande longue et que tu veux récupérer ton terminal :
bash# Lancer en arriere-plan directement
node server.js &
# Tu as lance sans & ? Pas de panique.
# Ctrl+Z suspend le processus (SIGTSTP)
# Puis reprends-le en arriere-plan
bg
# Voir les jobs du shell courant
jobs
# [1]+ Running node server.js &
# Remettre un job au premier plan
fg %1
Le problème : si tu fermes le terminal, les jobs en arriere-plan recoivent SIGHUP et meurent. C'est la que nohup et disown interviennent.
bash# nohup : ignore SIGHUP et redirige stdout vers nohup.out
nohup node server.js &
# disown : detache un job deja lance du shell
node server.js &
disown %1
# Combiner les deux pour etre tranquille
nohup node server.js > /var/log/app.log 2>&1 &
disown
En pratique, si tu deploies une vraie app, utilise plutot systemd ou un process manager comme pm2. nohup c'est bien pour un script ponctuel.
Les processus zombies
Un zombie, c'est un processus qui a fini son exécution mais dont le parent n'a pas encore lu le code de sortie (avec wait()). Il apparaît avec le statut Z dans ps :
bash# Trouver les zombies
ps aux | grep 'Z'
Un zombie ne consomme ni CPU ni mémoire. Il occupe juste une entree dans la table des processus. Un ou deux zombies, ce n'est pas grave. Des milliers, ca peut poser un problème. Pour s'en debarrasser, il faut tuer le processus parent -- le zombie sera alors "adopte" par PID 1 qui fera le menage.
PID 1 : pourquoi c'est important pour Docker
Sur un système Linux normal, PID 1 c'est systemd (ou init). Son rôle est d'adopter les processus orphelins et de recolter les zombies. Dans un conteneur Docker, PID 1 c'est le processus que tu définis dans ton CMD ou ENTRYPOINT.
Le problème : si ton PID 1 est node, Node ne gere pas les signaux comme un init system. Quand Docker envoie SIGTERM pour arrêter le conteneur, Node ne l'attrape pas par défaut et Docker attend 10 secondes avant d'envoyer SIGKILL.
dockerfile# Mauvais : node ne gere pas bien PID 1
CMD ["node", "server.js"]
# Mieux : utiliser tini comme init minimaliste
RUN apt-get install -y tini
ENTRYPOINT ["tini", "--"]
CMD ["node", "server.js"]
# Ou avec Docker >= 1.13
docker run --init node:20 node server.js
Dans ton code Node, tu peux aussi gerer les signaux explicitement :
javascriptprocess.on("SIGTERM", () => {
console.log("SIGTERM recu, fermeture propre...");
server.close(() => {
process.exit(0);
});
});
C'est un détail qui fait la différence entre un conteneur qui s'arrêté en 200ms et un qui attend 10 secondes a chaque déploiement.
Résumé
ps auxpour un instantane,htoppour du temps réel- Toujours SIGTERM avant SIGKILL
nohupetdisownpour detacher un processus du terminal- Les zombies ne sont dangereux qu'en grand nombre -- tue le parent
- PID 1 dans Docker merite une attention particulière, utilise
--initou tini
Article précédent : grep et find Article suivant : systemd