Ce guide s'adresse aux praticiens qui exploitent systemd en production et veulent gagner en confiance. Il fournit une liste de contrôle concrète avec des commandes vérifiables, des motifs de configuration sûrs, des étapes de validation, des routines de maintenance, des conseils pour la sauvegarde et la mise à niveau, ainsi que des approches de récupération rapide. L'accent est mis sur les changements réversibles, les résultats mesurables et des exemples testables localement avant tout déploiement.
À qui s'adresse ce guide :
- Développeurs responsables de services sur hôtes Linux.
- Consultants DevOps qui standardisent les opérations chez leurs clients.
- Équipes de démarrage qui ont besoin de pratiques opérationnelles fiables et légères.
Ce que vous retirerez :
- Une méthode d'inventaire concise pour comprendre votre environnement avant d'intervenir.
- Un chemin sûr pour configurer, durcir et limiter les ressources des services via les drop-ins.
- Des vérifications observables pour la correction et la performance.
- Des motifs de récupération pour les modes de défaillance courants.
- Une liste de contrôle répétable et une cadence de maintenance.
Prérequis :
- Accès shell avec sudo.
- Aisance à éditer des fichiers texte avec votre éditeur préféré.
- Connaissance de base de systemctl, journalctl et des concepts d'unités (service, target, timer).
Inventaire de version et d'environnement
Avant toute modification, établissez une base de référence. Cela réduit les surprises, accélère le triage et ancre le retour arrière. Exécutez ces commandes et conservez la sortie dans une note datée ou un ticket.
Faits de version principaux
# systemd et fonctionnalités de compilation
systemctl --version
# OS et noyau
cat /etc/os-release
uname -r
Résultat attendu : vous voyez la version de systemd (par exemple 249 ou 252), la distribution et le noyau. Enregistrez-les pour les vérifications de compatibilité.
Cibles par défaut et santé du démarrage
systemctl get-default
systemd-analyze
systemd-analyze blame | head -n 20
systemd-analyze critical-chain
Résultat attendu : la cible par défaut est généralement multi-user.target ou graphical.target. La sortie d'analyse montre le temps de démarrage et les unités les plus lentes.
Unités installées, activées et en échec
# Vue d'ensemble
systemctl list-units --type=service --state=running,failed
systemctl list-unit-files --type=service --state=enabled,disabled,masked
# Différences par rapport aux unités du fournisseur
systemd-delta
Résultat attendu : identifiez quels services sont actifs, lesquels ont échoué (state=failed) et quels surcharges existent.
Stockage et limites de taux de journald
# Vérifier la configuration de journald et le type de stockage
sed -n '1,200p' /etc/systemd/journald.conf | grep -E '^(Storage|SystemMaxUse|SystemMaxFileSize|RateLimit)' || true
journalctl --disk-usage
Résultat attendu : confirmez si les journaux sont persistants (Storage=persistent) et l'utilisation disque du journal.
Utilisez ce tableau pour capturer votre base de référence (les valeurs de la dernière colonne sont des exemples) :
| Élément | Commande | Exemple d'enregistrement |
|---|---|---|
| version systemd | systemctl --version | systemd 249 |
| OS et noyau | cat /etc/os-release; uname -r | Ubuntu 22.04; 5.15.0 |
| Cible par défaut | systemctl get-default | multi-user.target |
| Services activés | systemctl list-unit-files --type=service --state=enabled | myapp.service, nginx.service |
| Surcharges présentes | systemd-delta | /etc/systemd/system/myapp.service.d/override.conf |
| Stockage journal | journalctl --disk-usage | 512,0M |
Chemin de configuration sûr
La façon la plus sûre d'exploiter systemd en production est de privilégier les changements additifs et réversibles.
Principes :
- Ne modifiez pas les unités du fournisseur sous
/usr/lib/systemd/systemou/lib/systemd/system. - Utilisez des surcharges drop-in sous
/etc/systemd/system/NOM.service.d/. - Validez les changements avant et après le rechargement de systemd.
- Effectuez de petits changements audités et gardez-les sous contrôle de version.
Créer une surcharge drop-in (recommandé)
# Créer ou éditer une surcharge pour un service
sudo systemctl edit myapp.service
Cela ouvre un éditeur pour créer /etc/systemd/system/myapp.service.d/override.conf.
Exemple de surcharge :
# /etc/systemd/system/myapp.service.d/override.conf
[Service]
# Fiabilité
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30s
TimeoutStopSec=15s
# Contexte de sécurité
User=myapp
Group=myapp
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/myapp
# Contrôles de ressources (cgroups)
MemoryMax=512M
CPUWeight=200
# Environnement et commande de démarrage
EnvironmentFile=-/etc/myapp/myapp.env
WorkingDirectory=/var/lib/myapp
ExecStart=
ExecStart=/usr/local/bin/myapp --port=8080
Notes :
ExecStart=doit être absolu. La ligne videExecStart=efface la valeur du fournisseur avant de définir la vôtre.- Ajustez
MemoryMaxetCPUWeightselon votre planification de capacité.
Activez vos changements :
sudo systemd-analyze verify /etc/systemd/system/myapp.service
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
sudo systemctl status --no-pager myapp.service
Résultat attendu : le statut affiche active (running), le PID principal et aucun redémarrage immédiat.
Retour arrière : Si cela a été créé avec systemctl edit, vous pouvez le rétablir plus tard avec :
sudo systemctl revert myapp.service
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Configuration persistante de journald
Rendez les journaux persistants et bornés en taille. Éditez /etc/systemd/journald.conf (décommentez les lignes nécessaires) :
[Journal]
Storage=persistent
SystemMaxUse=1G
SystemMaxFileSize=128M
RateLimitIntervalSec=30s
RateLimitBurst=2000
Appliquez et vérifiez :
sudo systemctl restart systemd-journald
journalctl --disk-usage
Timers pour une maintenance sûre
Utilisez les timers systemd au lieu de cron pour une visibilité intégrée et une gestion des dépendances. Exemple : vidage hebdomadaire du journal.
Unité de service :
# /etc/systemd/system/journal-vacuum.service
[Unit]
Description=Vider le journal à 1G total
[Service]
Type=oneshot
ExecStart=/usr/bin/journalctl --vacuum-size=1G
Unité de timer :
# /etc/systemd/system/journal-vacuum.timer
[Unit]
Description=Vidage hebdomadaire du journal
[Timer]
OnCalendar=Sun 03:00
Persistent=true
[Install]
WantedBy=timers.target
Activez et vérifiez :
sudo systemctl daemon-reload
sudo systemctl enable --now journal-vacuum.timer
systemctl list-timers --all | grep journal-vacuum
Résultat attendu : le timer affiche une prochaine exécution et Dernière exécution comme n/a jusqu'à la première occurrence.
Hygiène des dépendances
- Utilisez
Wants=pour les relations souples ;Requires=pour les dépendances dures qui doivent être présentes. - Utilisez
After=pour ordonner le démarrage une fois les dépendances disponibles.After=n'implique pas de dépendance ; associez-le àWants=/Requires=quand nécessaire. - Gardez les dépendances minimales pour éviter les boucles et les démarrages lents.
Vérification et diagnostics
Après tout changement, vérifiez sous plusieurs angles : état de l'unité, journaux, compteurs de redémarrage, dépendances et performance.
État d'unité et journaux
systemctl status --no-pager myapp.service
journalctl -u myapp.service -b --no-pager | tail -n 50
Résultat attendu : Active (running). Les journaux récents contiennent une ligne de confirmation de démarrage et aucune boucle de plantage.
Comportement de redémarrage et codes de sortie
# Compteurs de redémarrage et statut de sortie du point de vue de systemd
systemctl show -p NRestarts,ExecMainStatus,ExecMainCode myapp.service
Résultat attendu : NRestarts=0 pour les services stables. Si les redémarrages sont non nuls, combinez journaux et codes de sortie pour diagnostiquer.
Validité d'unité et graphe de dépendances
# Vérifications statiques
systemd-analyze verify /etc/systemd/system/myapp.service
# Points chauds du démarrage
systemd-analyze blame | head -n 20
systemd-analyze critical-chain myapp.service
Résultat attendu : verify n'affiche aucune erreur. Blame aide à repérer les unités lentes ; critical-chain montre l'ordonnancement et les temps d'attente.
Vue cgroup des ressources
# Arborescence de processus en direct sous contrôle systemd
systemd-cgls
# Vue de type top par cgroup
systemd-cgtop
Résultat attendu : le service apparaît sous une tranche (par exemple system.slice), avec une utilisation CPU et mémoire conforme aux attentes.
Vérifications de descripteurs de fichiers et limites
Dans votre service, définissez par exemple :
[Service]
LimitNOFILE=65535
Vérifiez à l'exécution :
# Remplacez par le PID réel
cat /proc/$(systemctl show -p MainPID --value myapp.service)/limits | grep -i files
Résultat attendu : Max open files correspond à 65535.
Modes de défaillance et récupération
Utilisez le tableau ci-dessous pour associer les symptômes aux causes probables et aux premières actions.
| Signature de défaillance | Cause probable | Premières actions |
|---|---|---|
| Le service flappe toutes les quelques secondes | Restart=always avec plantage ; absence de readiness ; mauvaise config | Mettre Restart=on-failure ; inspecter journalctl -u ; corriger la config ; ajouter ExecStartPre |
| Délai au démarrage ou à l'arrêt | TimeoutStartSec/StopSec trop bas ; dépendance pas prête | Augmenter les timeouts ; ajouter After= et Wants= ; vérifier la santé de la dépendance |
| Boucle de dépendance détectée | Requires=/After= circulaires | Simplifier les dépendances ; remplacer Requires= par Wants= quand possible |
| Service reste inactif (dead) | Type=oneshot sans RemainAfterExit=yes | Ajouter RemainAfterExit=yes ou passer à Type=simple |
| Erreur ExecStart : non trouvé | Chemin relatif ou binaire manquant | Utiliser un chemin absolu ; vérifier permissions et SELinux/AppArmor si activés |
| Échec de permissions ou de bind | Mauvais User= ou port privilégié sans capacité | Exécuter sur port >1024, ou ajouter AmbientCapabilities=CAP_NET_BIND_SERVICE |
Motifs de récupération
Retour arrière rapide des drop-ins Si vous avez créé des surcharges avec systemctl edit :
sudo systemctl revert myapp.service
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Si vous avez ajouté manuellement des fichiers sous /etc/systemd/system/NOM.service.d/, déplacez-les :
sudo mkdir -p ~/unit-backup
sudo mv /etc/systemd/system/myapp.service.d/override.conf ~/unit-backup/
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
Désactiver et masquer pour contenir le rayon d'action Si un service nuit au nœud (par exemple boucles de plantage) :
sudo systemctl stop myapp.service
sudo systemctl disable myapp.service
sudo systemctl mask myapp.service
Démasquez quand prêt :
sudo systemctl unmask myapp.service
Modes rescue et emergency (dernier recours) Si le système ne peut pas démarrer normalement à cause d'unités cassées :
- Au chargeur de démarrage, définissez le paramètre noyau :
systemd.unit=rescue.target. - Alternativement, depuis un shell :
sudo systemctl isolate rescue.target. - Utilisez le mode emergency seulement si rescue échoue ; il monte des systèmes de fichiers minimaux.
Après avoir corrigé ou déplacé les unités cassées, revenez à la cible par défaut :
sudo systemctl default
Auditer les changements et confirmer la récupération
# Ce qui a changé par rapport aux défauts du fournisseur
systemd-delta
# Vérifier l'état cible et les échecs
systemctl --failed --no-pager
Liste de contrôle des opérations
Adoptez un flux cohérent : planifier, changer, vérifier et enregistrer.
Vérifications de sécurité avant changement
- Confirmez que vous avez un accès console ou un chemin hors bande si l'hôte devient inaccessible.
- Capturez un inventaire frais :
systemctl --version,systemctl list-units --type=service,systemd-delta. - Mettez en scène vos changements d'unités dans le contrôle de version.
- Préparez un plan de retour arrière : quels fichiers rétablir, quelles commandes exécuter et critères de succès.
Étapes de changement (exemple pour myapp.service)
- Créez une surcharge drop-in avec des changements ciblés.
- Validez le fichier d'unité :
sudo systemd-analyze verify /etc/systemd/system/myapp.service
- Rechargez systemd et redémarrez seulement l'unité affectée :
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
- Vérifiez le statut, les journaux, les compteurs de redémarrage et les dépendances :
systemctl status --no-pager myapp.service
journalctl -u myapp.service -b --no-pager | tail -n 100
systemctl show -p NRestarts myapp.service
systemd-analyze critical-chain myapp.service
- Observez 5 à 10 minutes si la charge le permet, puis décidez de conserver ou de revenir en arrière.
Enregistrement après changement
- Notez les changements, commandes exécutées et sorties observées.
- Ouvrez une tâche de suivi pour retirer les réglages temporaires ou durcir les limites après observation.
Opérations périodiques
Utilisez ce tableau pour standardiser les tâches récurrentes :
| Tâche | Fréquence | Commande | Résultat attendu |
|---|---|---|---|
| Revue des unités en échec | Quotidienne | systemctl --failed --no-pager | Zéro ou échecs acquittés |
| Vérification boucles de plantage | Quotidienne | systemctl list-units --state=failed; systemctl show -p NRestarts '*' | Aucun redémarrage inattendu |
| Santé taille du journal | Hebdomadaire | journalctl --disk-usage | Dans la politique (ex. <= 1G) |
| Revue statut timers | Hebdomadaire | systemctl list-timers --all | Tous les timers attendus actifs |
| Vérification dérive surcharges | Hebdomadaire | systemd-delta | Seules les surcharges intentionnelles présentes |
| Performance démarrage | Mensuelle | systemd-analyze blame | Aucune nouvelle unité lente |
| Sauvegarde fichiers d'unités | Mensuelle | tar ou capture VCS de /etc/systemd | Config archivée en sécurité |
Sauvegardes et mises à niveau
- Sauvegardez
/etc/systemd,/etc/systemd/systemet tout répertoireEnvironmentFile. - Pour les mises à niveau, enregistrez la version systemd actuelle et les fonctionnalités utilisées (ex.
ProtectSystem=strict). Testez un pilote étroit sur un hôte non critique et vérifiez les unités avecsystemd-analyze verify. Déployez seulement quand la vérification passe et les journaux sont propres.
Durcissement de sécurité gains rapides
Ajoutez ces éléments aux drop-ins de service quand applicable :
[Service]
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadWritePaths=/var/lib/myapp
CapabilityBoundingSet=~CAP_SYS_ADMIN CAP_SYS_MODULE
RestrictAddressFamilies=AF_INET AF_INET6
Vérifiez que l'unité démarre et fonctionne encore sous les charges attendues. Durcissez progressivement pour éviter de casser le comportement.
Résultats attendus et comment vérifier
Utilisez ces vérifications rapides après tout changement :
- Le service est actif et stable :
systemctl statusrapporte active (running) pendant au moins plusieurs minutes, avecNRestarts=0ou un nombre faible et explicable. - Les journaux sont sans bruit :
journalctl -u SERVICEmontre des lignes de démarrage saines et aucun message d'erreur répété. - L'utilisation des ressources est dans les limites :
systemd-cgtopindique CPU et mémoire conformes à vos cibles. - Les dépendances sont saines :
critical-chainn'affiche pas d'attentes ou de boucles inattendues. - Les timers s'exécutent :
list-timersmontre les prochaines et dernières heures pour les jobs de maintenance.
Si une vérification échoue, revenez au dernier changement, rechargez systemd et retestez. Évitez d'empiler plusieurs changements avant vérification.
Pièges courants à éviter
- Modifier les unités du fournisseur directement sous
/lib/systemd/system: la prochaine mise à jour de paquet écrase vos changements. Utilisez les drop-ins sous/etc/systemd/system. - Oublier
daemon-reloadaprès modification des fichiers d'unité : systemd ne verra pas vos éditions. Type=incorrect pour le service : les démons forking nécessitent souventType=forkinget unPIDFile; les processus simples utilisent généralementType=simple.ExecReloadmanquant : sans commande de rechargement, les tentatives de rechargement font un redémarrage complet ou échouent.Restart=alwaystrop agressif : cela peut masquer les boucles de plantage et gaspiller des ressources ; préférezRestart=on-failurepour beaucoup de services.- Confusion de dépendances :
After=sansWants=/Requires=ne crée pas de dépendance ; associez-les intentionnellement. - Journald non persistant : perdre les journaux au redémarrage complique la réponse aux incidents.
Un pilote minimal pour gagner en confiance
Choisissez un service non critique et appliquez ces étapes :
- Faites l'inventaire de l'hôte et de l'unité.
- Ajoutez un drop-in avec
Restart=on-failure,TimeoutStopSec=15setMemoryMax=512M. - Rendez journald persistant avec un plafond de 1G.
- Ajoutez un timer de vidage hebdomadaire du journal.
- Vérifiez la stabilité, l'utilisation des ressources et les journaux pendant une semaine.
- Documentez les résultats et décidez de déployer sur d'autres services.
Ce pilote étroit est rapide à inspecter localement et facile à annuler en cas de régression.
Conclusion
Des opérations systemd fiables en production découlent d'une base de référence claire, de petits changements réversibles, d'une vérification disciplinée et d'étapes de récupération prêtes à l'emploi. Utilisez les surcharges drop-in pour la sécurité, validez avec systemd-analyze verify, observez avec systemctl et journalctl, et automatisez la maintenance à faible risque avec les timers. Commencez par un pilote étroit, capturez les preuves et étendez à plus de services une fois vos vérifications au vert. Avec cette liste de contrôle en main, votre équipe peut améliorer la fiabilité des services sans ajouter de processus lourd ni d'outillage complexe. Les pratiques décrites ici s'échelonnent d'un seul hôte à des flottes gérées par la gestion de configuration, et vous gardent le contrôle lors des incidents.