Introduction
Systemd est puissant, mais ses messages d'erreur peuvent sembler opaques lorsqu'une unit échoue au démarrage ou redémarre en boucle. Ce guide se concentre sur les systemd common errors que vous verrez en pratique, pourquoi elles surviennent, comment les diagnostiquer vite, et des moyens sûrs de les corriger.
Vous obtiendrez :
- Un workflow de dépannage reproductible
- Un aide-mémoire de commandes d'inspection
- Des erreurs fréquentes, leurs causes, et des correctifs prêts à copier-coller
- Un plan pilote local pour s'entraîner sans risque avant de toucher la production
Workflow de dépannage (vue d'ensemble)
Utilisez cette séquence de bout en bout. C'est rapide, sûr et reproductible.
- Identifier l'unité et reproduire en sécurité
- Connaître le nom exact (ex. nginx.service). Évitez les suppositions.
- Si possible, reproduire d'abord en environnement non production.
- Inspecter le statut en premier
systemctl status nginx.service --no-pager -l
Regardez : état Active, ExecStart, Main PID, code/status, dernières lignes du journal.
- Lire les logs avec contexte
journalctl -xeu nginx.service --no-pager
# Ou restreindre au boot courant
journalctl -u nginx.service -b --no-pager
- Vérifier la syntaxe de l'unit et le fichier réellement chargé
systemctl cat nginx.service
systemctl show nginx.service -p FragmentPath -p DropInPaths
systemd-analyze verify /etc/systemd/system/nginx.service
- Tester la commande en dehors de systemd
- Exécutez la commande ExecStart manuellement (comme l'utilisateur du service si pertinent).
- Vérifiez l'existence et les permissions des binaires et scripts.
- Pour les scripts, confirmez le bit exécutable et un shebang valide.
- Vérifier l'ordonnancement et les dépendances
systemctl list-dependencies --reverse nginx.service
systemd-analyze critical-chain nginx.service
Ajustez Wants=, Requires=, et After= selon le besoin.
- Revoir le durcissement et les systèmes de fichiers
- Des options comme ProtectSystem, ReadWritePaths, PrivateTmp, DynamicUser et WorkingDirectory peuvent bloquer l'accès ou l'écriture.
- Si les écritures échouent, assouplissez prudemment les protections ou écrivez dans des chemins autorisés comme RuntimeDirectory.
- Appliquer les changements en sécurité et recharger
systemctl daemon-reload
systemctl restart nginx.service
Privilégiez les drop-ins via :
systemctl edit nginx.service
Cela crée /etc/systemd/system/nginx.service.d/override.conf.
- Confirmer et surveiller
systemctl is-active nginx.service && echo OK
journalctl -u nginx.service -b -n 50 --no-pager
Aide-mémoire de diagnostics
- Statut et derniers logs
systemctl status <unit> --no-pager -l
journalctl -xeu <unit> --no-pager
- Unit chargé et drop-ins
systemctl cat <unit>
systemctl show <unit> -p FragmentPath -p DropInPaths
- Valider la syntaxe de l'unit
systemd-analyze verify /etc/systemd/system/<unit>
- Logs limités au boot courant
journalctl -u <unit> -b --no-pager
- Dépendances et chaîne critique
systemctl list-dependencies --reverse <unit>
systemd-analyze critical-chain <unit>
- Environnement
systemctl show <unit> -p Environment -p EnvironmentFiles
Erreurs courantes et correctifs
Ci-dessous, les erreurs que vous verrez probablement, avec causes, diagnostics et remèdes sûrs.
1) "Unit <name>.service not found"
Symptôme :
systemctl start myapp
Failed to start myapp.service: Unit myapp.service not found.
Pourquoi :
- Fichier d'unit manquant ou mal nommé
- Modification sans "daemon-reload"
Diagnostiquer :
ls /etc/systemd/system/myapp.service /lib/systemd/system/myapp.service
systemctl daemon-reload && systemctl list-unit-files | grep myapp
Correctif :
- Placer le fichier dans /etc/systemd/system/myapp.service
- Corriger le nom et l'extension
- Recharger et démarrer :
systemctl daemon-reload
systemctl enable --now myapp.service
2) "Unit is masked"
Symptôme :
systemctl start docker
Failed to start docker.service: Unit docker.service is masked.
Pourquoi :
- L'unit est liée à /dev/null pour empêcher l'activation
Diagnostiquer :
ls -l /etc/systemd/system/docker.service
systemctl status docker
Correctif (comprendre d'abord pourquoi c'était masqué) :
systemctl unmask docker.service
systemctl enable --now docker.service
3) "Failed at step EXEC spawning ...: No such file or directory"
Symptôme :
systemd[1]: myapp.service: Failed at step EXEC spawning /usr/local/bin/myapp: No such file or directory
Pourquoi :
- Chemin ExecStart erroné ou binaire manquant
- Shebang du script incorrect
Diagnostiquer :
file /usr/local/bin/myapp
head -n1 /usr/local/bin/myapp
which myapp
Correctif :
- Pointer ExecStart vers le chemin absolu correct
- Pour un script, utiliser un shebang valide :
#!/usr/bin/env bash
- Rendre exécutable :
chmod +x /usr/local/bin/myapp
4) "Exec format error" ou permission denied pour les scripts
Symptôme :
... myapp.sh: Exec format error
Pourquoi :
- Fins de ligne CRLF (Windows)
- Non exécutable ou interpréteur manquant
Diagnostiquer et corriger :
file myapp.sh # indique CRLF si présent
sed -i 's/\r$//' myapp.sh # convertir en LF
chmod +x myapp.sh
head -n1 myapp.sh # vérifier le shebang
5) "Start request repeated too quickly" (boucle de crash)
Symptôme :
systemd[1]: myapp.service: Start request repeated too quickly.
Pourquoi :
- Le service sort rapidement, souvent avec Restart=always
Diagnostiquer :
journalctl -u myapp -b -n 100 --no-pager
systemctl show myapp -p Restart -p StartLimitBurst -p StartLimitIntervalSec
Correctif :
- Corriger la cause racine (mauvaise config, env manquant, mauvais chemin)
- Assouplir temporairement pour déboguer :
[Unit]
StartLimitIntervalSec=60
StartLimitBurst=10
[Service]
Restart=on-failure
RestartSec=2s
Appliquer via :
systemctl edit myapp.service
systemctl daemon-reload && systemctl restart myapp
6) "Dependency failed" ou problèmes d'ordre
Symptôme :
systemd[1]: Dependency failed for myapp.service
Pourquoi :
- L'unit dépend d'une autre inactive
- Le réseau n'est pas prêt, mais le service l'exige
Diagnostiquer :
systemctl list-dependencies --reverse myapp.service
systemd-analyze critical-chain myapp.service
Correctif (exemple : attendre le réseau) :
[Unit]
Wants=network-online.target
After=network-online.target
Avec systemd-networkd :
systemctl enable --now systemd-networkd-wait-online.service
7) EnvironmentFile introuvable
Symptôme :
... Failed to load environment files: No such file or directory
Pourquoi :
- Chemin EnvironmentFile erroné ou fichier manquant
Diagnostiquer :
systemctl show myapp -p EnvironmentFiles
ls -l /etc/default/myapp.env
Correctif :
- Créer le fichier et sécuriser les permissions :
install -m 0640 -o root -g root /dev/null /etc/default/myapp.env
echo 'MYAPP_PORT=8080' | tee -a /etc/default/myapp.env >/dev/null
- Dans l'unit :
[Service]
EnvironmentFile=/etc/default/myapp.env
- Recharger et redémarrer
8) WorkingDirectory n'existe pas
Symptôme :
... myapp.service: WorkingDirectory=/opt/myapp: No such file or directory
Pourquoi :
- Répertoire manquant ou mauvais propriétaire
Correctif :
install -d -o myuser -g myuser /opt/myapp
Ou utiliser RuntimeDirectory pour des chemins éphémères :
[Service]
RuntimeDirectory=myapp
WorkingDirectory=/run/myapp
9) Permission denied à cause du hardening
Symptôme :
... myapp: permission denied writing /var/log/myapp/output.log
Pourquoi :
- ProtectSystem=strict ou options similaires bloquent l'écriture
Diagnostiquer :
systemctl cat myapp | sed -n '/\[Service\]/,$p'
Correctif sûr :
- Écrire dans un RuntimeDirectory géré par systemd :
[Service]
RuntimeDirectory=myapp
# l'app écrit dans /run/myapp/
- Ou autoriser des chemins précis :
[Service]
ProtectSystem=strict
ReadWritePaths=/var/log/myapp
10) Champs d'unit invalides ou fautes de frappe
Symptôme :
... Failed to parse service type, ignoring: simple2
Pourquoi :
- Typos dans Type, ExecStart, ou noms de sections
Correctif :
- Comparer avec la documentation systemd.unit et systemd.service
- Valider :
systemd-analyze verify /etc/systemd/system/myapp.service
11) "Failed to connect to bus: No such file or directory" dans des conteneurs
Symptôme :
systemctl status
Failed to connect to bus: No such file or directory
Pourquoi :
- La plupart des conteneurs ne lancent pas systemd en PID 1
Correctif et conseils :
- Ne pas s'appuyer sur systemctl dans des conteneurs simples. Exécutez votre process en foreground et gérez-le via le runtime (ex. Docker).
- Si vous avez vraiment besoin de systemd en conteneur, utilisez une image faite pour cela et démarrez avec un init adapté après avoir évalué la sécurité et la complexité.
Plan pilote local
Commencez petit, mesurable, et facile à inspecter en local.
Objectif : démarrer un service minimal, déclencher deux erreurs courantes et les corriger.
- Créer un service simple
cat >/usr/local/bin/hello.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
: "${HELLO_MSG:=Hello}"
echo "$(date -Is) $HELLO_MSG" | tee -a /var/log/hello/hello.log
sleep 2
EOF
chmod +x /usr/local/bin/hello.sh
install -d -m 0755 /var/log/hello
cat >/etc/systemd/system/hello.service <<'EOF'
[Unit]
Description=Hello demo service
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
EnvironmentFile=-/etc/default/hello
ExecStart=/usr/local/bin/hello.sh
Restart=on-failure
RestartSec=1s
# Harden while allowing log writes
ProtectSystem=strict
ReadWritePaths=/var/log/hello
[Install]
WantedBy=multi-user.target
EOF
install -m 0644 /dev/null /etc/default/hello
printf 'HELLO_MSG=Hello from systemd\n' >> /etc/default/hello
systemctl daemon-reload
systemctl enable --now hello.service
systemctl status hello --no-pager -l
journalctl -u hello -b -n 50 --no-pager
- Vérification : valider le comportement
- Attendez que le service démarre et écrive dans /var/log/hello/hello.log.
- Confirmez avec :
tail -n 5 /var/log/hello/hello.log
- Introduire l'erreur A : mauvais chemin ExecStart
systemctl stop hello
systemctl edit hello.service
Ajouter dans le drop-in :
[Service]
ExecStart=
ExecStart=/usr/local/bin/hello-typo.sh
Puis :
systemctl daemon-reload
systemctl start hello
systemctl status hello -l --no-pager
Observer : Failed at step EXEC spawning ... No such file or directory.
Correctif A :
systemctl edit hello.service
Remplacer par :
[Service]
ExecStart=
ExecStart=/usr/local/bin/hello.sh
Recharger et redémarrer.
- Introduire l'erreur B : boucle de crash
sed -i '1i exit 1' /usr/local/bin/hello.sh # échec forcé
systemctl restart hello
journalctl -xeu hello --no-pager
Observer : Start request repeated too quickly si ça plante vite.
Correctif B :
- Retirer l'"exit" injecté :
sed -i '1{/exit 1/d;}' /usr/local/bin/hello.sh
- Optionnel : ajuster temporairement les limites pendant les tests :
systemctl edit hello.service
Ajouter :
[Unit]
StartLimitIntervalSec=60
StartLimitBurst=10
Recharger et redémarrer.
- Inspecter et nettoyer
journalctl -u hello -b --no-pager
systemctl disable --now hello
rm -f /etc/systemd/system/hello.service
systemctl daemon-reload
Pourquoi ce pilote fonctionne :
- Étroit et mesurable : démarrage, écriture de log, deux pannes induites, deux correctifs
- Facile à inspecter en local, sans effets de bord
Conclusion
Quand systemd échoue, suivez un workflow constant : inspecter le statut, lire les logs, valider l'unit, tester la commande manuellement, vérifier dépendances et durcissement, puis appliquer les changements en sécurité et recharger. Gardez un aide-mémoire de commandes et entraînez-vous avec un petit pilote local pour reconnaître vite les motifs. Avec ces étapes et exemples, les systemd error messages mènent à des causes claires et à des systemd fixes sûrs. Conservez les réflexes de systemd troubleshooting et de systemd debugging pour résoudre plus vite et avec confiance.