systemd : unités et services
Tu sais lire et écrire un fichier .service section par section, choisir le bon Type et le bon Restart, expliquer ce qu'est une cible, et distinguer une dépendance (Wants, Requires) d'un simple ordre de démarrage (After, Before).
Mis à jour le
Pourquoi on voit ça
La leçon précédente s’arrêtait sur systemd, le PID 1 : le premier processus, celui qui lance tout le reste. Mais comment sait-il quoi lancer, dans quel ordre, et quoi faire si un programme plante ?
Tout est écrit dans de petits fichiers texte : les unités. En DevOps, tu en liras tous les jours et tu en écriras dès que tu déploieras ta propre application sur un serveur. Savoir lire une unité, c’est comprendre pourquoi un service démarre, ou ne démarre pas.
Une unité, c’est quoi ?
Une unité est un objet que systemd sait gérer. Chaque unité est décrite par un fichier, et l’extension du fichier donne son type.
| Extension | Ce que l’unité gère | Exemple |
|---|---|---|
.service |
un programme à lancer et à surveiller | ssh.service |
.target |
un groupe d’unités, un état à atteindre | multi-user.target |
.timer |
une planification (lancer un service à une heure donnée) | apt-daily.timer |
.socket |
un port ou un socket en écoute | ssh.socket |
.mount |
un point de montage | home.mount |
Le type le plus courant, c’est le .service. On commence par lui.
Anatomie d’un fichier .service
Voici une unité complète pour une petite application web :
[Unit]
Description=Application web de démonstration
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/python3 /opt/monapp/app.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
Trois sections, toujours entre crochets. Chacune répond à une question.
[Install] ne sert à rien tant qu'on n'a pas fait enable.| Section | Question | Directives à connaître |
|---|---|---|
[Unit] |
Qui es-tu, et avec qui es-tu lié ? | Description, les dépendances |
[Service] |
Comment te lance-t-on ? | ExecStart, Type, Restart |
[Install] |
À quel moment du démarrage t’active-t-on ? | WantedBy |
Description: une phrase lisible par un humain. Elle s’affiche dans les commandes d’état et dans les journaux.ExecStart: la commande à lancer, avec son chemin complet (/usr/bin/python3, paspython3).WantedBy=multi-user.target: « quand le serveur atteint son état normal, lance-moi aussi ». C’est cette ligne qui est utilisée quand on active le service au démarrage.
Type : comment le programme se comporte
Type dit à systemd à quoi s’attendre une fois la commande lancée.
| Valeur | Comportement du programme | Cas typique |
|---|---|---|
simple |
il reste au premier plan ; le processus lancé par ExecStart est le service |
une application moderne (valeur par défaut) |
forking |
il se dédouble, le parent se termine et l’enfant continue en arrière-plan | un démon à l’ancienne |
oneshot |
il fait son travail puis se termine ; systemd attend la fin | un script de sauvegarde ou de nettoyage |
notify |
comme simple, mais le programme prévient lui-même systemd quand il est prêt |
un service qui met du temps à s’initialiser |
Si tu te trompes de Type, systemd comprend mal ce qu’il voit. Par exemple, avec simple sur un programme qui se détache, systemd voit le processus de départ se terminer et croit que le service s’est arrêté.
Restart : que faire quand il s’arrête
| Valeur | systemd relance le service… |
|---|---|
no |
jamais (valeur par défaut) |
on-failure |
seulement s’il s’est terminé en erreur (code de sortie différent de 0, plantage) |
always |
toujours, quelle que soit la raison de l’arrêt |
Dans tous les cas, un arrêt que tu demandes à systemd n’est pas suivi d’une relance.
Les cibles
Une cible (.target) ne lance rien elle-même. C’est un point de rassemblement : elle regroupe des unités et représente un état du système. « Atteindre la cible », c’est avoir démarré tout ce qu’elle regroupe.
| Cible | État du système |
|---|---|
multi-user.target |
plusieurs utilisateurs, réseau, mode texte : l’état normal d’un serveur |
graphical.target |
la même chose, plus l’interface graphique : un poste de travail |
rescue.target |
le mode dépannage : root seul, le strict minimum de services |
Au démarrage, systemd vise la cible par défaut. Pour la connaître :
systemctl get-default
En coulisses, default.target est un lien vers la vraie cible : get-default lit ce lien. Deux commandes voisines :
systemctl set-default multi-user.target
systemctl isolate rescue.target
set-default change la cible des prochains démarrages. isolate bascule tout de suite dans la cible demandée et arrête ce qui n’en fait pas partie : avec rescue.target, il ne reste que le minimum pour dépanner.
Tu comprends maintenant WantedBy=multi-user.target : ton service s’accroche à la cible que le serveur atteint à chaque démarrage.
Les dépendances
Les directives de dépendance s’écrivent dans [Unit]. Il y a deux questions différentes, et c’est le piège du chapitre :
- Faut-il lancer l’autre unité ? →
Wants,Requires - Dans quel ordre ? →
After,Before
Imagine qu’on écrit dans l’unité A :
| Directive dans A | Sens |
|---|---|
Wants=B |
B est souhaitée : lancer A lance aussi B, mais si B échoue, A démarre quand même |
Requires=B |
B est obligatoire : lancer A lance aussi B, et si B échoue, A ne démarre pas |
After=B |
A démarre après B |
Before=B |
A démarre avant B |
Conflicts=B |
A et B ne peuvent pas tourner ensemble : démarrer A arrête B |
After=B : A passe après B.After et Before ne règlent que l’ordre. After=B ne lance pas B : la directive dit seulement « si les deux doivent démarrer, B passe d’abord ». À l’inverse, Requires=B sans After=B lance les deux en même temps.
C’est pour ça qu’on les écrit souvent par paires :
[Unit]
Description=Application qui a besoin de sa base
Requires=postgresql.service
After=postgresql.service
Une analogie : pour un repas, Requires dit « pas de repas sans plat principal », After dit « le dessert se sert après le plat ». Ce sont deux informations distinctes.
Mesurer le démarrage : systemd-analyze
Puisque systemd lance tout, il sait combien de temps chaque chose a pris.
systemd-analyze
Cette commande affiche le temps total du dernier démarrage, découpé par grandes phases (noyau, puis espace utilisateur).
systemd-analyze blame
Celle-ci liste les unités de la plus lente à la plus rapide. Blame veut dire « accuser » : c’est la commande à lancer quand un serveur est devenu lent à démarrer.
À retenir
- Une unité = un objet géré par systemd, décrit par un fichier. L’extension donne le type :
.service,.target,.timer,.socket,.mount. - Un
.servicea trois sections :[Unit](identité et liens),[Service](ExecStart,Type,Restart),[Install](WantedBy). Type:simple(reste au premier plan),forking(se détache),oneshot(fait son travail et se termine).Restart:no,on-failure(seulement après une erreur),always.Wants= souhaitée,Requires= obligatoire.AfteretBeforene règlent que l’ordre :After=Bdans A veut dire que A démarre après B.systemctl get-defaultdonne la cible par défaut ;systemd-analyze blamedésigne les unités lentes au démarrage.
Entraînement
12 questions, dont 4 à compléter. Tu réponds, on passe à la suivante. La note arrive à la fin.
Ta note
Cartes · 8
Réviser les cartes ici
Pourquoi