Skip to Content

Chapitre 3.4 — Processus & signaux

⏱️ TL;DR — Un processus, c’est un programme en train de tourner : ton app Node, Nginx, Postgres, ton shell. Chacun a un numéro unique, le PID (Process ID), et un parent (le PPID) — ils forment un arbre. Pour voir ce qui tourne : ps aux (photo instantanée) ou, bien mieux, htop (vue interactive, live) où tu lis d’un coup le CPU, la RAM et le load average. Une commande peut tourner au premier plan (elle bloque ton terminal) ou en arrière-plan (&, Ctrl+Z + bg). Pour arrêter un processus, on lui envoie un signal : SIGTERM (15) est une demande polie de s’arrêter proprement, SIGKILL (9) est l’exécution brutale et sans appel. Règle : toujours SIGTERM d’abord, SIGKILL seulement s’il refuse de mourir.

🎯 Objectifs

  • Comprendre ce qu’est un processus, le PID, le PPID et l’arbre des processus.
  • Lister ce qui tourne avec ps et le suivre en direct avec htop.
  • Lancer et gérer des tâches en arrière-plan (&, Ctrl+Z, bg, fg, jobs, nohup).
  • Envoyer des signaux (kill, pkill, killall) et savoir pourquoi SIGTERM avant SIGKILL.
  • Garder une session vivante malgré une déconnexion SSH avec tmux / screen.

Qu’est-ce qu’un processus ?

Un programme est un fichier inerte sur le disque (/usr/bin/node, /usr/sbin/nginx). Un processus est ce programme une fois lancé : il vit en RAM, consomme du CPU, ouvre des fichiers et des connexions réseau. Un même programme peut donner plusieurs processus (plusieurs workers Nginx, plusieurs onglets Node…).

Chaque processus possède :

  • un PID (Process ID) : un numéro unique qui l’identifie tant qu’il vit. C’est par ce numéro qu’on lui parle (pour l’arrêter, par exemple).
  • un PPID (Parent Process ID) : le PID du processus qui l’a lancé. Car tout processus est créé par un autre.
  • un propriétaire (l’utilisateur sous lequel il tourne : deploy, www-data, root…) — celui dont il hérite les droits.

Comme chaque processus a un parent, ils forment un arbre. À la racine : le processus init (aujourd’hui systemd, PID 1), le tout premier lancé au démarrage, ancêtre de tous les autres.

💡 Réflexe — Le PID 1 est toujours le système d’init (systemd). Quand ton app tourne « en service » (Chapitre 3.5), son parent est systemd — c’est pour ça qu’elle survit à ta déconnexion et redémarre si elle tombe. Quand tu la lances à la main dans ton shell, son parent est ton shell : elle meurt avec lui. Cette différence de parenté est toute la raison d’être de systemd.

Voir ce qui tourne : ps et htop

ps prend une photo instantanée des processus. Deux invocations classiques, à connaître :

ps aux # TOUS les processus, tous utilisateurs, avec CPU/MEM (style BSD) ps -ef # idem, style System V, montre bien la colonne PPID (le parent)

Les colonnes utiles de ps aux : USER (propriétaire), PID, %CPU, %MEM, et la commande. On combine souvent avec un filtre :

ps aux | grep node # ne garder que les lignes contenant "node" pgrep -a node # les PID des process "node" (plus propre que grep) pidof nginx # le(s) PID d'un programme précis

Mais pour observer en direct, rien ne vaut htop : un tableau interactif, rafraîchi en continu, où l’on trie, filtre et tue les processus à la souris ou au clavier. (top est son ancêtre austère, présent partout par défaut ; htop est plus lisible mais parfois à installer : sudo apt install htop.)

htop # vue live ; quitte avec F10 ou q

Ce qu’on lit en haut de htop :

  • Les barres CPU (une par cœur) : le taux d’occupation de chaque vCPU.
  • La barre Mem : la RAM utilisée / totale (et Swp pour le swap — s’il grimpe, tu manques de RAM).
  • Le load average : trois chiffres (charge moyenne sur 1, 5 et 15 minutes). Repère clé : compare-les au nombre de vCPU. Un load de 2.0 sur une machine à 2 cœurs = pleinement chargée mais pas noyée ; le même 2.0 sur 1 seul cœur = surchargée, les tâches font la queue.

🐚 Au terminal — Le trio de diagnostic « ça rame, pourquoi ? » :

htop # CPU + RAM + load, en direct (le couteau suisse) free -h # mémoire : total / utilisé / libre / swap, lisible (-h = human) uptime # depuis quand la machine tourne + le load average sur 1/5/15 min

🧭 Sur FormaCampus — Un soir, formacampus.fr répond lentement. Réflexe : htop. L’équipe voit le load average à 7.0 sur un VPS à 2 vCPU (donc surchargé), une barre Mem au plafond et le swap qui monte. Coupable : un export PDF massif lancé par plusieurs formateurs en même temps, qui sature CPU et RAM. Diagnostic en trente secondes grâce à htop, là où « le site est lent » aurait pu partir dans toutes les directions. (Le lien avec le dimensionnement des ressources est vu en Partie 1.)

Premier plan, arrière-plan : reprendre la main

Quand tu lances une commande qui dure (un serveur, un long traitement), elle tourne au premier plan (foreground) et bloque ton terminal : tu ne récupères l’invite qu’à la fin. Pour continuer à travailler, tu la passes en arrière-plan (background).

long-traitement & # le "&" lance la commande directement en arrière-plan # -> le shell affiche [1] 12345 (numéro de job et PID) et te rend la main

Si tu as déjà lancé la commande au premier plan et qu’elle bloque :

# 1. Ctrl+Z -> SUSPEND le processus (il est mis en pause, en arrière-plan) bg # 2. le relance en arrière-plan (background), il reprend son travail jobs # liste les tâches lancées depuis CE shell, avec leur numéro [1], [2]... fg %1 # ramène la tâche numéro 1 au PREMIER plan (foreground)

⚠️ Piège — Une commande lancée avec & reste attachée à ton shell : si tu fermes le terminal (ou ta session SSH), elle reçoit un signal SIGHUP (hang up, « raccrochage ») et meurt avec le shell. Le & seul ne suffit pas à faire survivre un processus à ta déconnexion. C’est LE piège de « j’ai lancé mon serveur en SSH, je me déconnecte, et il s’arrête ».

Pour qu’une tâche survive à la déconnexion, deux outils :

nohup long-traitement & # nohup = "no hang up" : ignore le SIGHUP de fermeture # la sortie va dans un fichier nohup.out disown %1 # détache une tâche DÉJÀ lancée du shell (elle ne recevra plus SIGHUP)

Cela dit, nohup/disown sont des rustines : pour un vrai service de production, la bonne réponse n’est ni l’un ni l’autre, c’est systemd (Chapitre 3.5), qui gère proprement démarrage, redémarrage et logs.

Les signaux : parler à un processus

Pour communiquer avec un processus (surtout lui demander de s’arrêter), on lui envoie un signal : un message court, standardisé, identifié par un nom et un numéro. Les trois à connaître :

SignalNuméroEffetLe processus peut-il l’intercepter ?
SIGTERM15Demande polie de s’arrêter (le défaut de kill)Oui — il peut finir proprement
SIGKILL9Tue immédiatement, sans discussionNon — le noyau l’exécute d’office
SIGHUP1« Raccrochage » ; souvent : recharge ta configOui

La distinction SIGTERM vs SIGKILL est capitale :

  • SIGTERM (15) est une demande. Le processus la reçoit et peut réagir proprement : finir la requête en cours, vider ses tampons sur le disque, fermer sa connexion à la base, supprimer ses fichiers temporaires. C’est un arrêt en douceur.
  • SIGKILL (9) est une exécution. Le processus ne le reçoit même pas : le noyau le supprime sur-le-champ. Aucun nettoyage possible → risque de données corrompues, de fichiers à moitié écrits, de verrous laissés en place.

💡 RéflexeToujours SIGTERM d’abord, laisse quelques secondes, et n’emploie SIGKILL qu’en dernier recours, quand le processus refuse de mourir (bloqué, figé). Dégainer kill -9 par réflexe, c’est risquer une base de données corrompue ou un état incohérent. Le brutal se mérite : on l’utilise après avoir demandé poliment.

kill, pkill, killall

On envoie les signaux avec ces commandes :

kill 12345 # envoie SIGTERM (15) au PID 12345 -> arrêt propre demandé kill -15 12345 # explicitement SIGTERM (identique à ci-dessus) kill -9 12345 # SIGKILL : brutal, en DERNIER recours seulement kill -SIGHUP 12345 # SIGHUP : souvent "recharge ta config" pour un service pkill node # tue par NOM tous les process "node" (SIGTERM par défaut) killall node # idem : tous les processus nommés exactement "node" pgrep -a node # (pour VÉRIFIER d'abord quels PID on va viser)

⚠️ Piègepkill et killall frappent tous les processus qui correspondent au motif — d’un coup, sans confirmation. Un pkill node un peu large peut abattre plusieurs apps Node d’un même serveur (le front, un worker, un script), pas seulement celle que tu visais. Vérifie toujours avant, avec pgrep -a node (qui liste sans tuer), puis frappe. En prod, préfère viser le PID précis ou, mieux encore, passer par systemctl stop <service>.

📚 La doc — La liste complète des signaux est dans man 7 signal ; les commandes dans man kill, man pkill, man killall. Le trio SIGTERM / SIGKILL / SIGHUP couvre l’écrasante majorité des besoins d’administration courants.

tmux et screen : des sessions qui survivent

Problème récurrent en SSH : tu lances une opération longue (une migration de base, un gros rsync, un build), ta connexion saute au milieu, et… tout s’arrête, parce que le shell (et ses enfants) reçoit SIGHUP. La parade : un multiplexeur de terminal, tmux (ou l’ancien screen).

Un tmux crée une session qui tourne côté serveur, indépendante de ta connexion SSH. Tu peux t’en détacher (elle continue de tourner sans toi) et t’y rattacher plus tard, même depuis une autre machine.

tmux # ouvre une nouvelle session persistante # ... tu lances ton long traitement dedans ... # Ctrl+b puis d -> se DÉTACHER (la session continue à tourner en fond) tmux ls # lister les sessions tmux actives tmux attach # se RATTACHER à la session (retrouver son travail intact)

💡 Réflexe — Avant toute opération longue en SSH (migration, import, build, rsync massif), lance-la dans tmux. Si ta connexion tombe, le travail continue côté serveur et tu le retrouves en te rattachant. Sans ça, une micro-coupure réseau peut ruiner une migration à moitié faite. Pour un service permanent, en revanche, ce n’est pas tmux la solution mais systemdtmux est fait pour l’interactif long, pas pour héberger un service de prod.

🔒 Sécurité — Rappel de parenté : un processus hérite des droits de l’utilisateur qui l’a lancé. Une app lancée par deploy tourne avec les droits (limités) de deploy ; lancée par root, elle a tous les droits — d’où l’importance de faire tourner chaque service sous son utilisateur dédié (via User= dans systemd, Chapitre 3.5). Un processus compromis ne peut jamais faire plus que ce que son propriétaire a le droit de faire.

Un mot sur l’OOM killer

On l’a croisé en Partie 1 : quand la RAM est saturée, le noyau Linux déclenche l’OOM killer (Out Of Memory) et tue un processus pour survivre — souvent le plus gourmand, parfois ton app. C’est le noyau qui envoie un SIGKILL de sa propre initiative : dans les logs, tu verras un Killed ou une trace « Out of memory: Killed process… ». La leçon relie ce chapitre au précédent : surveiller la RAM dans htop/free -h, prévoir un peu de swap, et dimensionner correctement, sous peine de voir ses processus fauchés sans prévenir.

✏️ Exercices

Exercice 1 — Arrête proprement une app figée. Ton app Node (PID 4210) ne répond plus. Décris la marche à suivre pour l’arrêter sans risquer de corrompre ses données, et à quel moment il devient légitime d’employer la manière forte.

✅ Solution

D’abord la demande polie, qui laisse l’app se fermer proprement (finir la requête en cours, fermer la base) :

kill 4210 # SIGTERM (15) : arrêt en douceur demandé

On attend quelques secondes et on vérifie si elle est bien partie (ps -p 4210 ou pgrep -a node). Si — et seulement si — elle refuse de mourir (toujours là, figée), on emploie la manière forte :

kill -9 4210 # SIGKILL : brutal, en DERNIER recours

L’ordre compte : SIGKILL d’emblée aurait pu laisser des données à moitié écrites ou des verrous en place.

Exercice 2 — Diagnostique une lenteur. « Le serveur rame. » Quelle est la première commande que tu lances, et quels trois indicateurs regardes-tu en priorité pour savoir si c’est le CPU, la RAM ou une surcharge globale ?

✅ Solution

Première commande : htop (vue live de tout). Les trois indicateurs : (1) les barres CPU — saturées ? lequel des cœurs ? — pour un goulot processeur ; (2) la barre Mem (+ Swp) — RAM au plafond et swap qui monte = manque de mémoire, risque d’OOM killer ; (3) le load average (via htop ou uptime), à comparer au nombre de vCPU : un load nettement supérieur au nombre de cœurs = machine surchargée, tâches en file d’attente. En croisant les trois, on nomme le goulot au lieu de deviner.

🧠 Quiz de révision

1. Qu’est-ce que le PID et le PPID d’un processus ?

Le PID (Process ID) est le numéro unique qui identifie un processus tant qu’il vit ; c’est par lui qu’on lui envoie des signaux. Le PPID (Parent PID) est le PID du processus qui l’a lancé. Comme chaque processus a un parent, ils forment un arbre dont la racine est systemd (PID 1).

2. Quelle différence entre SIGTERM et SIGKILL, et lequel envoyer en premier ?

SIGTERM (15) est une demande polie : le processus la reçoit et peut s’arrêter proprement (finir, sauver, fermer). SIGKILL (9) est brutal : le noyau le supprime sur-le-champ, sans nettoyage possible (risque de corruption). On envoie toujours SIGTERM d’abord, et SIGKILL seulement si le processus refuse de mourir.

3. Pourquoi une commande lancée avec « & » meurt-elle quand on ferme la session SSH ?

Parce qu’elle reste rattachée au shell : à la fermeture, le shell (et ses enfants) reçoit un SIGHUP (raccrochage) et s’arrête. Le & met en arrière-plan mais ne détache pas de la session. Pour survivre : nohup/disown (rustines) ou, pour un vrai service, systemd.

4. Que lit-on dans le « load average », et comment l’interpréter ?

Trois chiffres : la charge moyenne du système sur 1, 5 et 15 minutes. On l’interprète par rapport au nombre de vCPU : un load égal au nombre de cœurs = pleinement chargé ; nettement au-dessus = surchargé (les tâches font la queue). Le même chiffre n’a pas le même sens sur 1 cœur ou sur 4.

5. Pourquoi tmux est-il utile en SSH, et quand ne PAS l’utiliser ?

tmux crée une session côté serveur, indépendante de la connexion SSH : elle survit à une déconnexion, on s’y détache et rattache à volonté — idéal pour une opération longue (migration, build). Ce n’est pas la solution pour un service permanent de prod : là, c’est systemd qui gère démarrage, redémarrage et logs.


Chapitre suivant : systemd & services — faire tourner ton app comme un vrai service qui redémarre tout seul.

Last updated on