Aller au contenu
Administration Linux medium

Un service actif qui ne répond pas

12 min de lecture

systemctl status affiche active (running), et pourtant le service ne répond plus. C'est le pire des cas, parce que l'outil sur lequel vous comptez vous ment par omission : systemd sait que le processus existe, il ne sait pas s'il fait son travail. Cette page vous donne la commande qui tranche en cinq secondes, puis les deux causes qui se cachent derrière ce symptôme, avec leurs signatures respectives.

Cette page complète Un service ne démarre pas, qui traite le cas où l'unité est en failed. Ici, l'unité est verte : c'est tout le problème.

  • Qualifier le symptôme avec curl et lire son code de sortie, qui désigne à lui seul la famille de la panne
  • Reconnaître un processus gelé avec ps, /proc et strace
  • Vérifier l'adresse d'écoute réelle d'un service, et comprendre pourquoi nginx -t ne verra jamais cette erreur
  • Réparer dans les deux cas, et prouver que le service répond à nouveau

Avant de toucher au serveur, posez la seule question qui oriente tout le reste : la connexion est-elle refusée ou suspendue ? Les deux produisent « ça ne marche pas » côté utilisateur, mais elles n'ont rien à voir. Un client qui attend indéfiniment a réussi à établir la connexion, donc quelque chose écoute. Un client refusé net n'a trouvé personne sur le port.

Fenêtre de terminal
curl -s -o /dev/null -w 'http %{http_code} en %{time_total}s\n' -m 5 http://127.0.0.1/
echo "code de sortie : $?"

Deux réponses possibles, deux diagnostics opposés :

Sortie observéeCodeCe que ça signifiePiste
http 000 en 5.002338s28La connexion s'établit, mais rien ne répond. Le client a attendu jusqu'au bout du -m 5.Le processus est gelé ou bloqué
http 000 immédiat7Connection refused : personne n'écoute sur ce port ou cette adresse.Mauvaise adresse d'écoute, ou service arrêté

Le temps de réponse est le signal. Cinq secondes pleines, c'est un timeout, donc un processus qui ne traite plus. Un échec instantané, c'est le noyau qui renvoie un RST parce qu'aucun socket n'écoute là où vous frappez.

Un processus gelé ne consomme pas de CPU, ne loggue rien, et garde son port ouvert. C'est le cas le plus déroutant, parce que toutes vos vérifications habituelles passent au vert. Il se produit quand le processus reçoit un SIGSTOP, quand il attend une entrée-sortie qui ne revient jamais (montage NFS mort, disque défaillant), ou quand il est bloqué sur un verrou.

Ce que systemd et ss vous disent (et c'est trompeur)

Section intitulée « Ce que systemd et ss vous disent (et c'est trompeur) »
Fenêtre de terminal
systemctl is-active nginx
systemctl status nginx --no-pager | head -6
active
Active: active (running) since Tue 2026-07-14 09:50:20 UTC; 3s ago

Le service est déclaré vivant. Le port, lui aussi, écoute toujours :

Fenêtre de terminal
ss -tlnp | grep -E ':80\b'
LISTEN 1 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=1667,fd=6),...)

Un détail trahit pourtant la panne. La première colonne, Recv-Q, vaut 1 au lieu de 0. Sur une socket en écoute, Recv-Q compte les connexions acceptées par le noyau mais jamais récupérées par l'application. Le noyau fait le travail, l'application ne vient plus chercher ses clients. Une file d'attente qui monte sur un socket LISTEN est la signature d'un processus qui ne traite plus.

L'état d'un processus est une lettre, et cette lettre vous dit tout. Récupérez le PID principal auprès de systemd, puis interrogez le noyau :

Fenêtre de terminal
MAIN=$(systemctl show -p MainPID --value nginx)
ps -o pid,stat,wchan:20,cmd -p "$MAIN"
grep -E '^(Name|State):' "/proc/$MAIN/status"
1667 Ts do_signal_stop nginx: master process /usr/sbin/nginx
Name: nginx
State: T (stopped)

T signifie stopped. Le processus est suspendu, il n'exécutera plus une seule instruction tant qu'on ne le réveillera pas. La colonne wchan précise même dans quelle fonction du noyau il dort : do_signal_stop. Les autres états à connaître : R (en exécution), S (en attente, normal), et surtout D (uninterruptible sleep), qui signale une entrée-sortie bloquée et qui, lui, ne se répare pas avec un signal.

Vérifiez tout le service, pas seulement le processus principal. Un serveur comme nginx délègue le travail à des workers :

Fenêtre de terminal
ps -o pid,stat,cmd -C nginx
1667 Ts nginx: master process /usr/sbin/nginx
1668 T nginx: worker process
1669 T nginx: worker process

Les trois processus sont figés. Si seul le master l'était, les workers continueraient de répondre et vous ne verriez aucune panne.

strace s'attache au processus et affiche les appels système qu'il passe au noyau. Sur un processus sain, la sortie défile. Sur un processus gelé, elle est vide, et l'outil vous dit pourquoi :

Fenêtre de terminal
timeout 5 strace -p "$MAIN"
strace: Process 1667 attached
--- stopped by SIGSTOP ---

Le diagnostic est écrit noir sur blanc. Notez que strace et lsof ne sont pas installés sur une image cloud minimale : c'est un dnf install -y strace lsof (ou apt install) qu'il vaut mieux avoir fait avant l'incident.

Le journal, lui, reste désespérément muet, et c'est logique : un processus gelé ne peut pas écrire ses propres logs. L'absence de trace n'est pas l'absence de problème.

Si la cause est un signal d'arrêt, on relance tout le groupe de processus du service. systemctl kill agit sur le cgroup entier, donc sur le master et tous ses workers, ce qu'un kill sur le seul PID principal ne ferait pas :

Fenêtre de terminal
systemctl kill --signal=SIGCONT nginx

Puis on prouve la réparation, ce qui n'est pas la même chose que constater l'absence d'erreur :

Fenêtre de terminal
ps -o pid,stat,cmd -C nginx
curl -s -o /dev/null -w 'http %{http_code} en %{time_total}s\n' -m 5 http://127.0.0.1/
1667 Ss nginx: master process /usr/sbin/nginx
1668 S nginx: worker process
apres reparation: http 200 en 0.000454s

Les états sont repassés en S, et la réponse revient en moins d'une milliseconde. Si l'état était D et non T, SIGCONT n'aurait rien changé : il aurait fallu traiter l'entrée-sortie bloquée, c'est-à-dire le montage réseau mort ou le disque défaillant.

Cas 2 : le service écoute sur la mauvaise adresse

Section intitulée « Cas 2 : le service écoute sur la mauvaise adresse »

Ce cas est banal, et il coûte pourtant des heures parce qu'il fonctionne parfaitement en local. Vous testez depuis le serveur, tout va bien. Les clients, eux, se prennent un refus immédiat. La cause est une directive d'écoute limitée au loopback au lieu de toutes les interfaces.

Fenêtre de terminal
grep -nE 'listen' /etc/nginx/nginx.conf
nginx -t
38: listen 127.0.0.1:80;
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

nginx -t valide la syntaxe, pas la pertinence. Le fichier est correct, le service démarre sans une erreur, et le journal est vide. Aucun outil de validation ne vous dira jamais qu'écouter sur 127.0.0.1 est une erreur d'exploitation : c'est une configuration parfaitement légitime, simplement pas celle que vous vouliez.

Fenêtre de terminal
curl -s -o /dev/null -w 'sur 127.0.0.1: http %{http_code}\n' -m 5 http://127.0.0.1/
curl -s -o /dev/null -w 'sur 10.0.2.15: http %{http_code}\n' -m 5 http://10.0.2.15/ ; echo "exit=$?"
sur 127.0.0.1: http 200
sur 10.0.2.15: http 000
exit=7

Depuis le serveur : 200. Depuis son adresse réseau : refus immédiat, code de sortie 7. C'est la définition même du symptôme « ça marche chez moi ». Testez toujours depuis l'adresse par laquelle vos clients arrivent, jamais depuis localhost.

Fenêtre de terminal
ss -tlnp | grep -E ':80\b'
LISTEN 0 511 127.0.0.1:80 0.0.0.0:* users:(("nginx",pid=1737,fd=6))

L'adresse d'écoute est 127.0.0.1:80 et non 0.0.0.0:80. 0.0.0.0 signifie toutes les interfaces, 127.0.0.1 signifie le loopback uniquement. Corrigez la directive, rechargez, et vérifiez que l'écoute est bien revenue sur toutes les interfaces avant de déclarer l'incident clos.

SymptômeCause probableVérificationCorrection
curl sort en 28 après le délai pleinProcessus gelé (T) ou bloqué en I/O (D)ps -o stat et /proc/<pid>/statussystemctl kill --signal=SIGCONT si T ; traiter le montage ou le disque si D
curl sort en 7 immédiatementRien n'écoute sur cette adressess -tlnp : comparer l'adresse d'écouteCorriger la directive d'écoute, recharger
Recv-Q monte sur un socket LISTENL'application n'accepte plus ses connexionsss -tlnpVoir le cas du processus gelé
Le service répond en local, pas depuis le réseauÉcoute sur 127.0.0.1ss -tlnpÉcouter sur 0.0.0.0 ou l'IP voulue
Le service répond, mais très lentementSaturation, pas blocageuptime, vmstat 1Voir Évaluer les performances
Le journal est vide alors que le service est casséProcessus gelé : il ne peut plus loggerps -o statNe pas conclure « pas de log, pas de problème »

Vérifiez que l'essentiel de ce guide est acquis. Les questions portent uniquement sur ce qui vient d'être expliqué ici.

Contrôle de connaissances

Validez vos connaissances avec ce quiz interactif

6 questions
6 min.
70% requis

Informations

  • Le chronomètre démarre au clic sur Démarrer
  • Questions à choix multiples, vrai/faux et réponses courtes
  • Vous pouvez naviguer entre les questions
  • Les résultats détaillés sont affichés à la fin

Lance le quiz et démarre le chronomètre

  • Le code de sortie de curl oriente le diagnostic : 28 (timeout) veut dire qu'on attend un processus qui ne répond plus, 7 (refused) veut dire que personne n'écoute là où vous frappez.
  • active (running) ne prouve rien. systemd surveille l'existence du processus, pas sa capacité à servir.
  • L'état du processus est une lettre : T (stoppé) se répare avec SIGCONT, D (I/O bloquée) ne se répare pas par un signal, il faut traiter la cause.
  • Recv-Q non nul sur un socket en écoute est la signature d'une application qui n'accepte plus ses connexions.
  • Un processus gelé ne loggue pas. Un journal vide pendant une panne est une information, pas un soulagement.
  • nginx -t valide la syntaxe, pas l'adresse d'écoute. Toujours vérifier avec ss -tlnp que le service écoute là où les clients arrivent.
  • Installez strace et lsof avant l'incident : ils sont absents des images cloud minimales.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn