E-NO
Concepts avancés systemd 7 min de lecture

systemd : concepts avancés expliqués avec des exemples pratiques - guide d'implémentation

calendar_today Publié : 2026-08-15
update Dernière mise à jour : 2026-08-15
analytics Efficacité SEO : 100%
Illustration du guide technique pour « systemd : concepts avancés expliqués avec des exemples pratiques - guide d'implémentation ».

systemd constitue l'épine dorsale des systèmes Linux modernes, pourtant de nombreux administrateurs n'interagissent avec lui qu'au travers des commandes basiques systemctl start et systemctl status. Cet article comble l'écart entre la gestion quotidienne des services et les mécanismes internes qui déterminent la fiabilité, la débogabilité et la sécurité opérationnelle. Vous apprendrez à inspecter les unités, manipuler le graphe de transaction, configurer les contrôles de ressources, diagnostiquer les échecs au démarrage et récupérer des modes de défaillance courants -- le tout avec des commandes tenant compte des versions et des étapes de vérification explicites.

Inventaire de version et d'environnement

Avant d'apporter des modifications, capturez la version exacte de systemd et la disposition de vos fichiers d'unité. Cet inventaire établit une base de référence pour chaque opération subséquente.

# Capturer la version de systemd et ses fonctionnalités
systemctl --version
# Exemple de sortie : systemd 255 (255.17-1ubuntu3.1)
#                  +PAM +AUDIT +SELINUX +APPARMOR +IMA +SMACK +SYSVINIT +UTMP +LIBCRYPTSETUP +GCRYPT +GNUTLS +ACL +XZ +LZ4 +ZSTD +SECCOMP +BLKID +ELFUTILS +KMOD +IDN2 -IDN +PCRE2 default-hierarchy=unified

Les indicateurs de fonctionnalités (par exemple +SECCOMP, +APPARMOR) indiquent quelles capacités de sécurité et de sandboxing sont compilées. Sur les systèmes antérieurs à la v239, la hiérarchie cgroup unifiée n'est pas nécessairement par défaut ; vérifiez avec cat /proc/cgroups.

Ensuite, énumérez les chemins de recherche d'unités et les répertoires drop-in :

# Afficher tous les chemins de chargement d'unités par ordre de priorité
systemd-analyze unit-paths
# Exemple de sortie :
# /etc/systemd/system
# /run/systemd/system
# /usr/lib/systemd/system
# ...

Listez les unités actives avec leur état de chargement, sous-état et chemin de fragment :

systemctl list-units --type=service --state=active --no-legend \
  | awk '{print $1}' \
  | xargs -r systemctl show -p LoadState,ActiveState,SubState,FragmentPath --value

Enregistrez la sortie avec un horodatage (date -Is) et stockez-la dans votre journal de modifications. Cette capture devient votre référence de restauration.

Prérequis : accès root ou sudo ; systemd v240+ recommandé pour la prise en charge complète des verbes systemd-analyze. Rayon d'impact : commandes en lecture seule ; aucun impact sur les services.

Chemin de configuration sécurisé

Les modifications de configuration doivent suivre une boucle observer-planifier-vérifier-récupérer. La plus petite modification justifiée est un fichier drop-in sous /etc/systemd/system/<unité>.d/override.conf, jamais une édition directe des unités du fournisseur dans /usr/lib/systemd/system/.

Contrôle des ressources avec cgroups v2

Le systemd moderne utilise la hiérarchie cgroup unifiée (cgroups v2). Pour limiter la mémoire et le CPU d'un service :

# Créer le répertoire drop-in
mkdir -p /etc/systemd/system/nginx.service.d/

# Écrire l'override avec des limites explicites
cat > /etc/systemd/system/nginx.service.d/override.conf <<'EOF'
[Service]
MemoryMax=512M
MemorySwapMax=256M
CPUQuota=200%
CPUWeight=100
IOWeight=100
EOF

Rechargez le démon et vérifiez que le fragment d'unité reflète le changement :

systemctl daemon-reload
systemctl show nginx.service -p MemoryMax,CPUQuota --value
# Attendu : MemoryMax=536870912, CPUQuota=200000

Redémarrez le service et confirmez que les limites cgroup sont appliquées :

systemctl restart nginx.service
cat /sys/fs/cgroup/system.slice/nginx.service/memory.max
# Devrait afficher 536870912 (512M en octets)

Drop-in de durcissement de sécurité

Appliquez un profil de défense en profondeur sans modifier l'unité upstream :

cat > /etc/systemd/system/nginx.service.d/hardening.conf <<'EOF'
[Service]
# Réduction des privilèges
User=nginx
Group=nginx
DynamicUser=yes
# Espaces de noms de système de fichiers
ProtectSystem=strict
ProtectHome=yes
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictNamespaces=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
MemoryDenyWriteExecute=yes
# Bornage des capacités
CapabilityBoundingSet=CAP_NET_BIND_SERVICE CAP_DAC_OVERRIDE
AmbientCapabilities=CAP_NET_BIND_SERVICE
# Restrictions réseau
RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
# Répertoires temporaires privés
PrivateTmp=yes
PrivateDevices=yes
ProtectProc=invisible
ProtectSys=strict
EOF

Vérifiez que l'unité analysée inclut toutes les directives :

systemctl daemon-reload
systemd-analyze verify nginx.service
# Aucune sortie signifie syntaxe OK
systemctl show nginx.service -p ProtectSystem,ProtectHome,CapabilityBoundingSet --value

Vérification : systemctl is-active nginx.service retourne active ; systemctl status nginx.service n'affiche aucune erreur Main PID. Récupération : systemctl revert nginx.service supprime tous les drop-ins et restaure les valeurs par défaut du fournisseur ; puis systemctl daemon-reload && systemctl restart nginx.service.

Vérification et diagnostics

Lorsqu'un service se comporte mal, allez au-delà de systemctl status vers des diagnostics structurés.

Inspection du graphe de transaction

systemd résout les dépendances comme un graphe de transaction. Pour voir pourquoi une cible entraîne des unités spécifiques :

# Afficher la transaction complète pour multi-user.target
systemd-analyze dot multi-user.target | dot -Tpng -o /tmp/multi-user.png
# Nécessite le paquet graphviz

Pour une analyse en mode texte, listez les dépendances inverses et les contraintes d'ordre :

# Qu'est-ce qui nécessite nginx.service ?
systemctl list-dependencies --reverse nginx.service

# Qu'est-ce qui doit démarrer avant nginx ?
systemctl list-dependencies --before nginx.service

# Qu'est-ce qui démarre après nginx ?
systemctl list-dependencies --after nginx.service

Analyse de performance et d'échec au démarrage

Identifiez les unités lentes pendant le démarrage :

systemd-analyze blame --no-pager | head -20
# Exemple de sortie :
# 12.345s docker.service
#  8.211s mysql.service
#  4.102s networkd-dispatcher.service

Corrélez avec la chaîne critique (le plus long chemin de dépendance vers default.target) :

systemd-analyze critical-chain --no-pager
# Affiche la chaîne avec @ (actif) et + (inactif)

Pour un démarrage échoué, inspectez le journal avec des filtres structurés :

# Afficher seulement les unités échouées du dernier démarrage
journalctl -b -1 -p err -u "*" --no-pager

# Suivre les logs d'une unité spécifique avec métadonnées
journalctl -u nginx.service -o json-pretty -f

Débogage des conditions d'unité

Les unités avec ConditionPathExists=, ConditionKernelVersion= ou AssertSecurity= peuvent être ignorées silencieusement. Pour tester les conditions sans démarrer :

systemd-analyze condition nginx.service
# Sortie : ConditionPathExists=/etc/nginx/nginx.conf -> "ConditionPathExists=/etc/nginx/nginx.conf" (true)
#         ConditionKernelVersion=>=3.10 -> "ConditionKernelVersion=>=3.10" (true)

Si une condition échoue, l'unité entre dans l'état skipped. Vérifiez avec :

systemctl show nginx.service -p ConditionResult,ConditionTimestamp --value

Vérification : toutes les unités cibles rapportent active ou inactive (dead) comme prévu ; aucune unité failed dans systemctl --failed. Récupération : systemctl reset-failed efface l'état d'échec ; systemctl daemon-reload réanalyse les fichiers d'unité après modifications.

Modes de défaillance et récupération

Épuisement de la limite de démarrage

Un service qui plante répétitivement atteint les valeurs par défaut de StartLimitIntervalSec et StartLimitBurst (5 démarrages en 10 secondes). L'unité entre en failed avec Result=start-limit-hit.

Diagnostic :

systemctl show nginx.service -p StartLimitIntervalUSec,StartLimitBurst,NRestarts --value
journalctl -u nginx.service -n 50 --no-pager

Atténuation : Ajustez les limites dans un drop-in :

cat > /etc/systemd/system/nginx.service.d/start-limits.conf <<'EOF'
[Service]
StartLimitIntervalSec=60
StartLimitBurst=10
Restart=on-failure
RestartSec=5s
EOF
systemctl daemon-reload && systemctl reset-failed nginx.service && systemctl restart nginx.service

Interblocage d'ordre de dépendance

Deux unités avec After= et Requires= formant un cycle provoquent un interblocage de transaction. systemd signale Transaction is destructive ou Ordering cycle found.

Diagnostic :

systemd-analyze verify --ordering-cycles
systemd-analyze dot --ordering-cycles | grep -E '->.*->'

Résolution : Remplacez Requires= par Wants= là où une dépendance dure n'est pas nécessaire, ou introduisez une cible intermédiaire pour briser le cycle.

Épuisement des ressources cgroup

Un service dépassant MemoryMax reçoit SIGKILL (OOM kill). Le journal affiche Killed ou Out of memory.

Diagnostic :

journalctl -u nginx.service -g "Killed\|OOM\|memory" --no-pager
cat /sys/fs/cgroup/system.slice/nginx.service/memory.events
# Affiche le compteur oom_kill

Récupération : Augmentez MemoryMax ou optimisez l'application. Désactivez temporairement la limite pour restaurer le service :

systemctl set-property nginx.service MemoryMax=infinity
# Ou modifiez le drop-in et daemon-reload

Échec d'activation par socket

Une unité socket échoue à passer le descripteur de fichier au service. Causes courantes : incompatibilité SocketMode, ListenStream= manquant dans l'unité socket, ou service ne déclarant pas Sockets= ou n'utilisant pas sd_listen_fds().

Diagnostic :

systemctl status nginx.socket
journalctl -u nginx.socket -u nginx.service --no-pager
systemctl show nginx.socket -p ListenStream,FileDescriptorName --value

Récupération : Assurez-vous que l'unité socket a ListenStream=80 et que l'unité service a Sockets=nginx.socket (ou utilise Type=notify avec sd_listen_fds()). Redémarrez les deux : systemctl restart nginx.socket nginx.service.

Liste de contrôle opérationnelle

Utilisez cette liste avant et après toute modification systemd en production.

Avant modification :

  • [ ] Enregistrer la sortie de systemctl --version et systemd-analyze unit-paths avec horodatage.
  • [ ] Capturer l'état actuel des unités : systemctl list-units --type=service --state=active,failed --no-legend > /var/tmp/units-before-$(date -Is).txt.
  • [ ] Identifier l'unité exacte et le chemin drop-in à modifier.
  • [ ] Écrire le drop-in dans un fichier de staging ; valider avec systemd-analyze verify <unité>.
  • [ ] Définir la commande de vérification attendue et sa sortie de succès.
  • [ ] Documenter la commande de restauration (systemctl revert <unité> ou git checkout pour les unités gérées).

Exécution de la modification :

  • [ ] Appliquer le drop-in : systemctl daemon-reload.
  • [ ] Vérifier l'unité analysée : systemctl show <unité> -p <propriétés-modifiées> --value.
  • [ ] Redémarrer ou recharger l'unité : systemctl restart <unité> ou systemctl reload <unité>.
  • [ ] Exécuter la commande de vérification ; comparer la sortie au résultat attendu.

Après modification :

  • [ ] Confirmer que systemctl is-active <unité> retourne active.
  • [ ] Vérifier systemctl status <unité> pour avertissements ou conditions dégradées.
  • [ ] Examiner le journal pour erreurs : journalctl -u <unité> -p warning..err --since "5 minutes ago".
  • [ ] Vérifier que les unités dépendantes restent saines : systemctl list-dependencies --reverse <unité> | xargs -r systemctl is-active.
  • [ ] Enregistrer la capture d'état final avec horodatage.
  • [ ] Mettre à jour le runbook ou le journal de modifications avec commandes, sorties et écarts éventuels.

Restauration d'urgence :

  • [ ] systemctl revert <unité> (supprime tous les drop-ins /etc pour cette unité).
  • [ ] systemctl daemon-reload.
  • [ ] systemctl restart <unité>.
  • [ ] Vérifier la santé du service selon les étapes post-modification.

Conclusion

Maîtriser les concepts avancés de systemd transforme le dépannage réactif en opérations prévisibles. En inventoriant les versions et chemins d'unités, en appliquant la configuration via des drop-ins versionnés, en diagnostiquant avec le graphe de transaction et les requêtes de journal structurées, et en se préparant aux modes de défaillance spécifiques -- épuisement des limites de démarrage, cycles de dépendance, OOM kill cgroup, ruptures d'activation par socket -- vous gagnez le contrôle sur le système d'initialisation qui sous-tend chaque charge de travail Linux. Chaque modification suit une boucle observer-planifier-vérifier-récupérer avec commandes explicites, sorties attendues et étapes de restauration testées. La prochaine fois qu'un service échoue à démarrer ou qu'un démarrage se bloque, vous tracerez la chaîne de dépendance exacte, inspecterez la condition ou limite de ressource précise, et restaurerez le service sans deviner. Traitez systemd non comme une boîte noire mais comme une plateforme programmable et inspectable -- et votre sécurité opérationnelle s'améliorera mesurablement.

Recherches connexes

Score de qualité de l’article

Utilité pour le lecteur 100%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO