🐧 Edge Linux Debian · diagnostic & exploitation

Chapitre 03
systemd : état des services & remise en route

Objectifs du chapitre

1. systemd, PID 1 : le chef d'orchestre

Au démarrage de Debian, le noyau lance un unique processus qui porte le numéro PID 1 : systemd. C'est lui qui démarre tout le reste, dans le bon ordre, en respectant les dépendances, et qui supervise ensuite chaque service : s'il meurt, systemd peut le relancer ; s'il refuse de démarrer, systemd le marque failed et garde la trace.

Tout ce que gère systemd est décrit par des unités. Les types qu'on croise sur un edge :

SuffixeType d'unitéExemple
.serviceun service (démon)docker.service, chronyd.service
.socketun socket qui active un service à la demandessh.socket
.timerun déclencheur périodique (cron moderne)backup.timer (chapitre 8)
.targetun groupe/étape (ancien « runlevel »)multi-user.target
.mountun point de montagedata.mount

2. Lire l'état d'un service

La commande de base, systemctl status, donne une photo complète :

maint@edge-cell12:~$ systemctl status chronyd
● chronyd.service - chrony, an NTP client/server
     Loaded: loaded (/lib/systemd/system/chronyd.service; enabled; preset: enabled)
     Active: active (running) since Tue 2026-04-08 06:14:02 CEST; 87 days ago
       Docs: man:chronyd(8)
   Main PID: 612 (chronyd)
      Tasks: 1 (limit: 4571)
     Memory: 2.1M
        CPU: 41.800s
     CGroup: /system.slice/chronyd.service
             └─612 /usr/sbin/chronyd -F 1

Les deux lignes qui portent l'information :

Deux axes indépendants à ne pas confondre : enabled/disabled répond à « démarre-t-il au boot ? », active/inactive à « tourne-t-il maintenant ? ». Un service peut être enabled mais inactive (planté), ou active mais disabled (lancé à la main, il ne reviendra pas après reboot — piège classique : « ça marchait, puis on a rebooté et c'est parti »).

Balayer tout le système

maint@edge-cell12:~$ systemctl --failed
  UNIT                 LOAD   ACTIVE SUB    DESCRIPTION
● edge-gateway.service loaded failed failed Edge Gateway (OPC-UA → MQTT)
1 loaded units listed.

systemctl --failed est la première commande de diagnostic : elle liste tout ce qui est en échec, rien d'autre. Ici, le service edge est tombé. On regarde ensuite son statut détaillé.

3. Lire un service failed

maint@edge-cell12:~$ systemctl status edge-gateway
● edge-gateway.service - Edge Gateway (OPC-UA → MQTT)
     Loaded: loaded (/etc/systemd/system/edge-gateway.service; enabled)
     Active: failed (Result: exit-code) since Sat 2026-07-04 08:03:11 CEST; 2min ago
    Process: 21874 ExecStart=/usr/bin/docker compose -f /opt/edge/compose.yml up (code=exited, status=1)
   Main PID: 21874 (code=exited, status=1)

Jul 04 08:03:11 edge-cell12 docker[21874]: Error response from daemon: driver failed programming
Jul 04 08:03:11 edge-cell12 docker[21874]: external connectivity: port 1883 already allocated
Jul 04 08:03:11 edge-cell12 systemd[1]: edge-gateway.service: Failed with result 'exit-code'.

Le bloc status se lit de bas en haut : systemd affiche les dernières lignes de journal de l'unité. Ici la cause est explicite — port 1883 déjà alloué : un ancien conteneur MQTT tient encore le port. On saura le résoudre au chapitre 6 ; pour l'instant, l'important est que systemctl status a montré la cause sans qu'on aille chercher ailleurs.

Le réflexe canonique face à un service en défaut : systemctl status <unité> pour la photo + les dernières erreurs, puis journalctl -u <unité> -e (chapitre 4) pour le fil complet. Neuf pannes sur dix se diagnostiquent dans ces deux commandes.

4. Les verbes d'action

Une fois la cause comprise, on agit. Quatre paires de verbes couvrent l'exploitation ; tous demandent sudo.

CommandeEffetQuand
start / stoplance / arrête maintenantaction ponctuelle
restartstop puis startrelancer un service planté ou après changement de config d'app
reloadrecharge la config sans couperquand le service le supporte (ex. ssh, chronyd)
enable / disable(dé)active le démarrage au bootrendre un service permanent
maint@edge-cell12:~$ sudo systemctl restart edge-gateway
maint@edge-cell12:~$ systemctl is-active edge-gateway
active
maint@edge-cell12:~$ systemctl is-enabled edge-gateway
enabled

enable --now combine enable + start en une fois, et disable --now combine disable + stop. Pratique pour « je veux que ce service tourne et revienne au boot » d'un seul geste : sudo systemctl enable --now edge-gateway.

Voir les dépendances

Le service edge dépend de Docker, qui dépend du réseau… list-dependencies déroule l'arbre :

maint@edge-cell12:~$ systemctl list-dependencies edge-gateway
edge-gateway.service
● ├─docker.service
● ├─system.slice
● └─network-online.target
●   └─...

Utile quand un service ne démarre pas « sans raison » : souvent c'est une dépendance en amont qui a échoué (Docker pas prêt, réseau pas monté). On corrige la cause, pas le symptôme.

5. Écrire l'unité du service edge

Pour que le service edge démarre au boot, survive à un crash et s'intègre aux journaux, on l'enveloppe dans une unité systemd. Fichier /etc/systemd/system/edge-gateway.service :

[Unit]
Description=Edge Gateway (OPC-UA → MQTT)
Requires=docker.service
After=docker.service network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=/opt/edge
# Démarre la stack Docker Compose au premier plan (pas de -d)
ExecStart=/usr/bin/docker compose -f /opt/edge/compose.yml up
ExecStop=/usr/bin/docker compose -f /opt/edge/compose.yml down
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Les clés importantes :

Après toute création ou édition d'unité, on recharge la définition avant d'agir :

maint@edge-cell12:~$ sudo systemctl daemon-reload      # relit les fichiers d'unités
maint@edge-cell12:~$ sudo systemctl enable --now edge-gateway
Created symlink /etc/systemd/system/multi-user.target.wants/edge-gateway.service → /etc/systemd/system/edge-gateway.service.

Oublier daemon-reload après avoir modifié un fichier .service est l'erreur la plus courante : systemd continue d'utiliser l'ancienne version en mémoire et tes changements semblent « ignorés ». systemd te prévient d'ailleurs avec un Warning: The unit file … changed on disk. Run 'systemctl daemon-reload'. Réflexe : j'édite une unité → je fais daemon-reload → j'agis.

Deux écoles pour le service edge, toutes deux valables : (a) une unité systemd qui lance docker compose up (ci-dessus) — systemd est le superviseur, les logs vont dans journald ; (b) laisser Docker gérer avec restart: unless-stopped dans le compose (chapitre 7) — c'est le démon Docker qui relance. On peut combiner : le plus robuste est d'avoir Docker enabled au boot et une politique de restart dans le compose, l'unité systemd servant surtout d'interrupteur clair et de point de log.

6. Mesurer le démarrage : systemd-analyze

Un edge qui met deux minutes à booter, c'est deux minutes sans remontée de données. systemd-analyze dit où part le temps.

maint@edge-cell12:~$ systemd-analyze
Startup finished in 3.891s (kernel) + 18.4s (userspace) = 22.3s

maint@edge-cell12:~$ systemd-analyze blame | head -5
    11.204s docker.service
     4.019s edge-gateway.service
     1.337s NetworkManager-wait-online.service
      812ms chronyd.service
      330ms systemd-journald.service

blame classe les unités par durée de démarrage. Ici Docker domine (normal : il monte ses réseaux et volumes), suivi du service edge. Si un service inattendu traîne en tête, c'est une piste — souvent un *-wait-online qui attend un réseau qui ne vient jamais.

Le pendant côté automate : le CPU S7-1500 a lui aussi une séquence de démarrage (STOP → STARTUP → RUN) et des diagnostics de mise en route dans TIA. La philosophie est jumelle : un redémarrage n'est pas instantané, il suit un ordre de dépendances, et on peut en mesurer/lire chaque étape. Sur l'edge, cet ordre, c'est systemd qui le tient.

Récapitulatif

Exercices

Exercice 1 — « Ça marchait, puis on a rebooté »

Un service tournait, mais après le dernier reboot il n'est plus là. systemctl status montre active: inactive (dead). Quelle est la cause probable, et quelle commande la confirme puis la corrige ?

Voir la solution
$ systemctl is-enabled monservice
disabled            # ← voilà : il n'était pas activé au boot
$ sudo systemctl enable --now monservice

Le service avait été lancé à la main (start) mais jamais enable. Il tournait donc jusqu'au reboot, puis n'est pas revenu. enable --now le relance et le rend permanent. C'est la confusion enabled/active du §2.

Exercice 2 — Un service en échec : la démarche

systemctl --failed montre edge-gateway.service en failed. Écris la séquence exacte pour comprendre pourquoi, puis le relancer une fois la cause traitée.

Voir la solution
$ systemctl status edge-gateway        # photo + dernières erreurs
$ journalctl -u edge-gateway -e        # fil de journal complet (ch. 4)
# … on lit la cause, on la corrige (port occupé, image manquante, disque plein…) …
$ sudo systemctl restart edge-gateway
$ systemctl is-active edge-gateway
active

On ne relance jamais en boucle sans lire la cause : un restart aveugle sur un service qui échoue à cause d'un disque plein ou d'un port occupé rejouera le même échec. Lire d'abord, agir ensuite.

Exercice 3 — Mes changements d'unité sont ignorés

Tu modifies /etc/systemd/system/edge-gateway.service pour ajouter RestartSec=30, tu fais restart, mais le comportement n'a pas changé. Pourquoi, et comment corriger ?

Voir la solution

systemd travaille sur la version en mémoire de l'unité, pas sur le fichier fraîchement édité. Il faut lui dire de relire les fichiers :

$ sudo systemctl daemon-reload
$ sudo systemctl restart edge-gateway

daemon-reload recharge les définitions ; restart applique le nouveau comportement au service qui tourne. L'ordre compte : reload puis restart.