Gestion des services¶
La gestion des services systemd couvre la création, modification, débogage et optimisation des unit files. Cette section explique comment créer des services robustes et maintenables.
Cycle de vie d'un service¶
Un service systemd passe par plusieurs étapes :
- Création : Écriture du unit file
- Installation : Placement et activation
- Démarrage : Lancement du service
- Surveillance : Monitoring et logs
- Modification : Mise à jour de la configuration
- Débogage : Résolution de problèmes
Création d'un service¶
Anatomie d'un service complet¶
# /etc/systemd/system/myapp.service
[Unit]
Description=My Application Service
Documentation=https://myapp.example.com/docs
After=network-online.target
Wants=network-online.target
Requires=postgresql.service
[Service]
Type=simple
User=myapp
Group=myapp
WorkingDirectory=/opt/myapp
EnvironmentFile=/etc/myapp/environment
ExecStartPre=/usr/local/bin/myapp-prestart.sh
ExecStart=/usr/local/bin/myapp --config /etc/myapp/config.yaml
ExecReload=/bin/kill -HUP $MAINPID
ExecStop=/usr/local/bin/myapp-stop.sh
Restart=on-failure
RestartSec=5s
TimeoutStartSec=30s
TimeoutStopSec=10s
# Sécurité
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/myapp /var/log/myapp
# Limites ressources
MemoryMax=2G
CPUQuota=200%
TasksMax=500
# Logging
StandardOutput=journal
StandardError=journal
SyslogIdentifier=myapp
[Install]
WantedBy=multi-user.target
Also=myapp-worker.service
Étapes de création¶
1. Créer l'utilisateur système¶
# Créer un utilisateur dédié sans shell
sudo useradd -r -s /usr/sbin/nologin -d /opt/myapp myapp
# Créer les répertoires
sudo mkdir -p /opt/myapp /var/lib/myapp /var/log/myapp
sudo chown -R myapp:myapp /opt/myapp /var/lib/myapp /var/log/myapp
2. Écrire le unit file¶
3. Valider la syntaxe¶
# Vérifier la syntaxe
systemd-analyze verify /etc/systemd/system/myapp.service
# Voir le fichier tel que systemd le comprend
systemctl cat myapp.service
4. Recharger systemd¶
5. Activer et démarrer¶
# Activer au boot
sudo systemctl enable myapp.service
# Démarrer
sudo systemctl start myapp.service
# Vérifier
sudo systemctl status myapp.service
Modification de services¶
Drop-in files (méthode recommandée)¶
Plutôt que de modifier directement un unit file système, utilisez des drop-ins :
Cela crée /etc/systemd/system/nginx.service.d/override.conf :
Avantages :
- Ne modifie pas le fichier original
- Survit aux mises à jour du paquet
- Plusieurs drop-ins peuvent coexister
- Facile à versionner
Modification complète¶
Pour remplacer complètement un unit :
# Copier le unit système
sudo cp /usr/lib/systemd/system/nginx.service /etc/systemd/system/
# Éditer
sudo nano /etc/systemd/system/nginx.service
# Recharger
sudo systemctl daemon-reload
sudo systemctl restart nginx.service
Voir les modifications¶
# Voir tous les overrides
systemd-delta
# Voir la configuration effective
systemctl cat nginx.service
# Voir seulement les drop-ins
systemctl show nginx.service -p FragmentPath -p DropInPaths
Débogage¶
Service ne démarre pas¶
# Voir l'état détaillé
systemctl status myapp.service
# Logs récents
journalctl -u myapp.service -n 50
# Logs depuis le dernier boot
journalctl -u myapp.service -b
# Suivre en temps réel
journalctl -u myapp.service -f
# Niveau de détail maximum
SystemdLogLevel=debug
systemctl daemon-reload
systemctl restart myapp.service
journalctl -u myapp.service -n 100
Vérifier les dépendances¶
# Voir les dépendances
systemctl list-dependencies myapp.service
# Voir les dépendances inverses
systemctl list-dependencies --reverse myapp.service
# Voir les services requis non démarrés
systemctl list-dependencies myapp.service | grep -E '●|×'
Analyser les temps de démarrage¶
# Temps de démarrage du service
systemd-analyze blame | grep myapp
# Chaîne critique
systemd-analyze critical-chain myapp.service
Tester manuellement¶
# Exécuter comme systemd le ferait
sudo -u myapp /usr/local/bin/myapp --config /etc/myapp/config.yaml
# Avec l'environnement systemd
sudo systemd-run --unit=myapp-test \
--working-directory=/opt/myapp \
--setenv=ENV_VAR=value \
/usr/local/bin/myapp
Reload vs Restart¶
Reload (rechargement à chaud)¶
Envoie un signal (généralement SIGHUP) pour recharger la configuration sans interrompre le service.
Configuration :
Restart (redémarrage complet)¶
Arrête puis redémarre le service. Provoque une interruption.
Try-restart¶
Redémarre seulement si le service est déjà actif.
Reload-or-restart¶
Tente un reload, sinon fait un restart.
Templates de services¶
Les templates permettent de créer plusieurs instances d'un service :
# /etc/systemd/system/myapp@.service
[Unit]
Description=My App Instance %i
After=network.target
[Service]
Type=simple
User=myapp
ExecStart=/usr/local/bin/myapp --instance %i --port 808%i
Environment="INSTANCE=%i"
WorkingDirectory=/var/lib/myapp/%i
[Install]
WantedBy=multi-user.target
Utilisation :
# Démarrer plusieurs instances
systemctl start myapp@1.service
systemctl start myapp@2.service
systemctl start myapp@prod.service
# Activer au boot
systemctl enable myapp@1.service myapp@2.service
# Voir toutes les instances
systemctl list-units 'myapp@*'
Variables disponibles :
%i: Identifiant de l'instance (après @)%I: Identifiant échappé%n: Nom complet de l'unit%N: Nom sans le suffixe%p: Prefix (nom sans @)%H: Hostname%u: Username
Bonnes pratiques¶
1. Toujours documenter¶
[Unit]
Description=Clear and concise description
Documentation=https://docs.example.com/myapp
Documentation=man:myapp(8)
2. Utiliser des utilisateurs dédiés¶
3. Définir des timeouts¶
4. Gérer les échecs¶
5. Limiter les ressources¶
6. Sécuriser le service¶
[Service]
NoNewPrivileges=yes
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=yes
ReadOnlyPaths=/
ReadWritePaths=/var/lib/myapp
7. Logger correctement¶
8. Tester avant production¶
# Vérifier la syntaxe
systemd-analyze verify myapp.service
# Tester le démarrage
systemctl start myapp.service
systemctl status myapp.service
# Tester le reload
systemctl reload myapp.service
# Tester le restart
systemctl restart myapp.service
# Tester l'arrêt
systemctl stop myapp.service
Automatisation¶
Générer un service avec un script¶
#!/bin/bash
# generate-service.sh
NAME=$1
USER=$2
EXEC=$3
cat > /etc/systemd/system/${NAME}.service <<EOF
[Unit]
Description=${NAME} Service
After=network.target
[Service]
Type=simple
User=${USER}
ExecStart=${EXEC}
Restart=on-failure
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable ${NAME}.service
Utiliser systemd-run pour tests¶
# Créer un service temporaire
systemd-run --unit=test-app \
--property=User=myapp \
--property=WorkingDirectory=/opt/myapp \
/usr/local/bin/myapp
# Service qui s'autodétruit après exécution
systemd-run --scope /usr/bin/mycommand
La maîtrise de la gestion des services systemd permet de créer des services robustes, sécurisés et facilement maintenables.