Tu viens d’installer Nginx sur ton serveur. Il tourne. Mais demain, après un reboot, il ne sera peut-être plus là. Tu veux qu’un script Python démarre automatiquement au boot ? Qu’un service redémarre tout seul s’il plante ?
Tout ça, c’est le travail de systemd — le système d’init qui gère tous les services sur les distributions Linux modernes.
Ce guide est fait pour toi si…
Section intitulée « Ce guide est fait pour toi si… »Fondamentaux sur les Services Systemd
Section intitulée « Fondamentaux sur les Services Systemd »Systemd a révolutionné la gestion des services dans l’écosystème Linux,
apportant une approche plus cohérente et intégrée par rapport aux systèmes
d’initialisation antérieurs. Au cœur de systemd se trouve systemctl, un outil
de commande puissant qui simplifie la gestion des services, des processus
d’arrière-plan et même du démarrage du système lui-même.
J’ai écrit un article sur ce qu’est systemd, que vous pouvez consulter
ici.
Fichiers de Configuration des Services
Section intitulée « Fichiers de Configuration des Services »Chaque service ou unité géré par systemd est décrit par un fichier de configuration spécifique. Ces fichiers contiennent des informations essentielles sur le service, telles que son nom, son exécutable, ses dépendances, etc. Les fichiers de configuration des services peuvent être situés dans plusieurs emplacements, notamment :
/etc/systemd/system/: Pour les fichiers de configuration système qui affectent tous les utilisateurs./usr/lib/systemd/system/: Pour les fichiers de configuration système fournis par les packages de la distribution.~/.config/systemd/user/: Pour les fichiers de configuration spécifiques à l’utilisateur.
Ces fichiers de configuration permettent de personnaliser le comportement des services et de définir des options spécifiques. Un exemple de service :
[Unit]Description=OpenBSD Secure Shell serverDocumentation=man:sshd(8) man:sshd_config(5)After=network.target auditd.serviceConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Service]EnvironmentFile=-/etc/default/sshExecStartPre=/usr/sbin/sshd -tExecStart=/usr/sbin/sshd -D $SSHD_OPTSExecReload=/usr/sbin/sshd -tExecReload=/bin/kill -HUP $MAINPIDKillMode=processRestart=on-failureRestartPreventExitStatus=255Type=notifyRuntimeDirectory=sshdRuntimeDirectoryMode=0755
[Install]WantedBy=multi-user.targetAlias=sshd.serviceCe fichier d’unité ssh.service est divisé en trois catégories principales,
chacune avec un rôle spécifique dans la configuration et le comportement du
service SSH sous systemd.
- [Unit] : Cette section contient les métadonnées et les conditions de démarrage du service.
- [Service] : Cette section précise comment exécuter et gérer le service SSH.
- [Install] : Cette section configure l’intégration du service dans le système.
Ces sections permettent à systemd de gérer SSH avec des règles précises pour l’activation, l’exécution et l’intégration du service dans le système.
États d’un Service
Section intitulée « États d’un Service »Avant de plonger dans les commandes systemctl, il est essentiel de comprendre
les états d’un service dans systemd. Un service peut se trouver dans l’un des
états suivants :
- Actif (active) : Le service est en cours d’exécution et fonctionne correctement.
- Inactif (inactive) : Le service est arrêté et n’est pas en cours d’exécution.
- Échec (failed) : Le service a rencontré un problème et a échoué.
- Masqué (masked) : Le service est masqué, ce qui signifie qu’il ne peut pas être activé ou démarré.
- Alias (alias) : L’unité est un alias vers une autre unité. Elle ne peut pas être démarrée indépendamment.
- Statique (static) : L’unité est statique, ce qui signifie qu’elle ne peut pas être activée ou désactivée.
- Désactivé (disabled) : Le service est désactivé et ne sera pas démarré au démarrage.
Les Commandes systemctl
Section intitulée « Les Commandes systemctl »Maintenant que nous avons acquis une compréhension des services systemd,
plongeons dans les commandes systemctl, qui sont essentielles pour la gestion
des services et des unités.
Liste des Services
Section intitulée « Liste des Services »Pour lister les différents services disponibles, vous pouvez utiliser la commande suivante :
systemctl list-unit-files --type=serviceUNIT FILE STATE VENDOR PRESETaccounts-daemon.service enabled enabledapparmor.service enabled enabledapt-daily-upgrade.service static -apt-daily.service static -apt-news.service static -autovt@.service alias -binfmt-support.service enabled enabledblk-availability.service enabled enabledchrony.service masked enabledchronyd.service masked enabledcockpit-motd.service static -cockpit-wsinstance-http.service static -cockpit-wsinstance-https-factory@.service static -Cette commande affichera une liste de tous les fichiers d’unité de type service présents sur votre système, montrant s’ils sont activés ou désactivés.
Démarrer un Service
Section intitulée « Démarrer un Service »La commande systemctl start est utilisée pour démarrer un service. Par
exemple, pour démarrer le service Apache, vous pouvez utiliser la commande
suivante :
sudo systemctl start apache2.serviceArrêter un Service
Section intitulée « Arrêter un Service »Pour arrêter un service en cours d’exécution, vous pouvez utiliser la commande
systemctl stop. Par exemple, pour arrêter le service Apache, utilisez :
sudo systemctl stop apache2.serviceRedémarrer un Service
Section intitulée « Redémarrer un Service »Lorsque vous avez apporté des modifications à la configuration d’un service, il
peut être nécessaire de le redémarrer pour que les changements prennent effet.
La commande systemctl restart permet de redémarrer un service. Par exemple,
pour redémarrer le service Nginx :
sudo systemctl restart nginx.serviceActiver un Service au Démarrage
Section intitulée « Activer un Service au Démarrage »Lorsque vous souhaitez qu’un service démarre automatiquement avec le système au
démarrage, vous pouvez l’activer à l’aide de la commande systemctl enable. Par
exemple, pour activer le service SSH :
sudo systemctl enable ssh.serviceDésactiver un Service au Démarrage
Section intitulée « Désactiver un Service au Démarrage »Si vous ne voulez plus qu’un service démarre automatiquement au démarrage, vous
pouvez le désactiver avec la commande systemctl disable. Par exemple, pour
désactiver le service MySQL :
sudo systemctl disable mysql.serviceVérifier l’État d’un Service
Section intitulée « Vérifier l’État d’un Service »Pour vérifier l’état d’un service, utilisez la commande systemctl status. Elle
vous fournira des informations détaillées sur l’état actuel du service,
notamment s’il est actif, inactif ou en échec. Par exemple :
● fail2ban.service - Fail2Ban Service Loaded: loaded (/lib/systemd/system/fail2ban.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2023-12-06 08:42:17 CET; 23h ago Docs: man:fail2ban(1) Main PID: 179095 (fail2ban-server) Tasks: 5 (limit: 21485) Memory: 13.3M CPU: 15.801s CGroup: /system.slice/fail2ban.service └─179095 /usr/bin/python3 /usr/bin/fail2ban-server -xf start
déc. 06 08:58:24 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 08:58:24 internal fail2ban-client[184816]: OKdéc. 06 08:58:24 internal systemd[1]: Reloaded Fail2Ban Service.déc. 06 09:16:03 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 09:16:03 internal fail2ban-client[189091]: 2023-12-06 09:16:03,519 fail2ban [189091]: ERROR Failed during configuration: While reading f>déc. 06 09:16:03 internal systemd[1]: fail2ban.service: Control process exited, code=exited, status=255/EXCEPTIONdéc. 06 09:16:03 internal systemd[1]: Reload failed for Fail2Ban Service.déc. 06 09:17:31 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 09:17:31 internal fail2ban-client[189879]: OKRecharger la Configuration
Section intitulée « Recharger la Configuration »Lorsque vous apportez des modifications aux fichiers de service systemd, vous
devez recharger la configuration pour que systemd prenne en compte les
changements. Utilisez la commande systemctl daemon-reload pour cela :
sudo systemctl daemon-reloadJournalisation et Dépannage
Section intitulée « Journalisation et Dépannage »La gestion des services ne se limite pas seulement à les démarrer et les
arrêter, elle implique également de surveiller leur comportement, de
diagnostiquer les problèmes et de dépanner les éventuelles erreurs. Cette
section se penche sur la journalisation avec
journalctl et sur les méthodes
de dépannage courantes.
Journalisation avec journalctl
Section intitulée « Journalisation avec journalctl »Systemd introduit une approche centralisée de la journalisation à l’aide de
l’outil journalctl. Cela signifie que toutes les informations de
journalisation des services et du système sont accessibles depuis une seule
source. Pour consulter le journal d’un service spécifique, utilisez la commande
suivante :
journalctl -u nom_du_serviceCette commande affichera les entrées de journal associées à ce service, ce qui est précieux pour le dépannage.
Filtrer les Entrées du Journal
Section intitulée « Filtrer les Entrées du Journal »journalctl offre une variété d’options de filtrage pour affiner les résultats
de la journalisation. Vous pouvez filtrer par date, niveau de gravité,
utilisateur, etc. Par exemple, pour afficher les entrées de journal du service
Apache depuis hier jusqu’à aujourd’hui :
journalctl -u fail2ban.service --since yesterday --until today 07:45:04
déc. 06 08:42:17 internal systemd[1]: Started Fail2Ban Service.déc. 06 08:42:17 internal fail2ban-server[179095]: Server readydéc. 06 08:58:24 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 08:58:24 internal fail2ban-client[184816]: OKdéc. 06 08:58:24 internal systemd[1]: Reloaded Fail2Ban Service.déc. 06 09:16:03 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 09:16:03 internal fail2ban-client[189091]: 2023-12-06 09:16:03,519 fail2ban [189091]: ERROR Failed during configuration: While reading f>déc. 06 09:16:03 internal systemd[1]: fail2ban.service: Control process exited, code=exited, status=255/EXCEPTIONdéc. 06 09:16:03 internal systemd[1]: Reload failed for Fail2Ban Service.déc. 06 09:17:31 internal systemd[1]: Reloading Fail2Ban Service...déc. 06 09:17:31 internal fail2ban-client[189879]: OKdéc. 06 09:17:31 internal systemd[1]: Reloaded Fail2Ban Service.Vérification des Erreurs
Section intitulée « Vérification des Erreurs »La journalisation est particulièrement utile pour identifier et résoudre les erreurs. Vous pouvez rechercher les entrées de journal contenant des erreurs en utilisant la commande suivante :
journalctl -p err -u nom_du_serviceCela affichera uniquement les entrées de journal avec un niveau de gravité “error”.
Dépannage des Échecs de Service
Section intitulée « Dépannage des Échecs de Service »Lorsqu’un service échoue au démarrage, journalctl peut être votre meilleur
allié pour comprendre la cause du problème. Examinez les messages d’erreur et
les détails du journal pour identifier les problèmes potentiels.
Plus d’infos
Section intitulée « Plus d’infos »Vous retrouverez plus d’informations sur la journalisation avec journalctl dans
le guide suivant.
Création de Services personnalisés
Section intitulée « Création de Services personnalisés »Systemd offre la possibilité de créer des services personnalisés pour répondre aux besoins spécifiques de votre système. Cette section vous guidera à travers le processus de création de services systemd, vous permettant ainsi de personnaliser le comportement de votre système.
Création d’un Fichier de Service
Section intitulée « Création d’un Fichier de Service »Pour créer un service personnalisé, commencez par créer un fichier de service
systemd. Ces fichiers sont généralement stockés dans le répertoire
/etc/systemd/system/. Voici un exemple de fichier de service simple pour un
script personnalisé :
[Unit]Description=Mon Service PersonnaliséAfter=network.target
[Service]ExecStart=/usr/bin/mon_script.shType=simple
[Install]WantedBy=multi-user.target- La section
[Unit]contient des métadonnées sur le service, telles que sa description et ses dépendances. - La section
[Service]spécifie comment le service doit être exécuté, y compris le chemin vers l’exécutable. - La section
[Install]définit comment le service doit être activé au démarrage.
Charger et Activer le Service
Section intitulée « Charger et Activer le Service »Après avoir créé le fichier de service, vous devez le charger dans systemd à l’aide de la commande suivante :
sudo systemctl daemon-reloadEnsuite, vous pouvez activer le service pour qu’il démarre au démarrage du système :
sudo systemctl enable mon_service.serviceDémarrer et Gérer le Service
Section intitulée « Démarrer et Gérer le Service »Une fois le service activé, vous pouvez le démarrer avec la commande :
sudo systemctl start mon_service.serviceVous pouvez également l’arrêter, le redémarrer, le désactiver, etc., en utilisant les commandes systemctl que nous avons vues précédemment.
Quelques recommandations
Section intitulée « Quelques recommandations »Lors de la création de services personnalisés, voici quelques astuces et bonnes pratiques à garder à l’esprit :
- Assurez-vous que le chemin vers l’exécutable est correctement spécifié dans le fichier de service.
- Utilisez des scripts de démarrage ou des programmes fiables et sécurisés.
- Documentez soigneusement le service en ajoutant des commentaires dans le fichier de service pour expliquer son objectif et ses dépendances.
- Effectuez des tests approfondis pour vous assurer que le service fonctionne comme prévu.
- Surveillez régulièrement les journaux du service pour détecter les problèmes potentiels.
En créant des services personnalisés, vous pouvez étendre les fonctionnalités de votre système Linux de manière flexible et adaptée à vos besoins spécifiques. Cependant, assurez-vous de suivre les meilleures pratiques de création et de gestion des services pour garantir la stabilité et la sécurité de votre système.
Sécurité
Section intitulée « Sécurité »Voici quelques bonnes pratiques pour maintenir un environnement sécurisé. Tout d’abord, appliquez le principe du moindre privilège, en limitant les permissions des services à ce qui est strictement nécessaire. Utilisez les mécanismes d’isolation offerts par systemd, tels que les cgroups et les namespaces, pour restreindre l’accès et les ressources des services. Limitez également les ressources utilisées par chaque service, comme la mémoire et la CPU, pour éviter qu’un service malveillant ne monopolise les ressources du système.
La journalisation est essentielle : surveillez régulièrement les logs avec
journalctl pour détecter toute activité suspecte. Assurez-vous de maintenir le
système à jour en appliquant régulièrement les mises à jour de sécurité pour
corriger les vulnérabilités. Configurez un pare-feu pour restreindre le
trafic réseau aux seules machines autorisées et suivez les bonnes pratiques de
gestion des mots de passe et de l’authentification. Enfin, mettez en place
un système de surveillance de la sécurité pour identifier et réagir
rapidement aux violations ou comportements anormaux.
Optimisation du temps de boot
Section intitulée « Optimisation du temps de boot »En plus de journalctl, vous pouvez utiliser systemd-analyze pour analyser
les performances de démarrage de votre système. Cette commande vous donne des
informations détaillées sur le temps nécessaire au démarrage de chaque unité.
systemd-analyze blame44.099s apt-daily-upgrade.service36.972s apt-daily.service 2.941s plocate-updatedb.service 2.014s postfix@-.service 2.006s fstrim.service 1.748s systemd-networkd-wait-online.service 1.231s docker.service 408ms dev-mapper-internal\x2d\x2dvg\x2droot.deviceCette commande vous montrera quelles unités prennent le plus de temps au démarrage, ce qui peut vous aider à identifier les goulots d’étranglement potentiels.
Contrôle de connaissances
Section intitulée « Contrôle de connaissances »Tu penses maîtriser systemctl ? Vérifie-le en 5 minutes !
Ce quiz teste ta compréhension des commandes et concepts que tu viens de découvrir. Si tu as bien lu ce guide, tu devrais atteindre les 80% sans difficulté.
Contrôle de connaissances
Validez vos connaissances avec ce quiz interactif
Informations
- Le chronomètre démarre au clic sur Démarrer
- Questions à choix multiples, vrai/faux et réponses courtes
- Vous pouvez naviguer entre les questions
- Les résultats détaillés sont affichés à la fin
Lance le quiz et démarre le chronomètre
Vérification
(0/0)Profil de compétences
Quoi faire maintenant
Ressources pour progresser
Des indices pour retenter votre chance ?
Nouveau quiz complet avec des questions aléatoires
Retravailler uniquement les questions ratées
Retour à la liste des certifications
Pour aller plus loin
Section intitulée « Pour aller plus loin »Tu maîtrises maintenant systemctl pour gérer tes services. Mais l’administration Linux ne s’arrête pas là :
Approfondir Linux
Section intitulée « Approfondir Linux »Questions fréquentes
Section intitulée « Questions fréquentes »Pourquoi systemd ?
| Aspect | SysVinit (ancien) | systemd (moderne) |
|---|---|---|
| Démarrage | Séquentiel (lent) | Parallèle (rapide) |
| Dépendances | Scripts manuels | Automatiques |
| Journalisation | Fichiers dispersés | Centralisée (journalctl) |
| Surveillance | Cron/scripts | Intégrée (watchdog) |
| Isolation | Limitée | cgroups, namespaces |
Composants principaux
- systemctl : gestion des services
- journalctl : consultation des logs
- systemd-analyze : analyse du démarrage
- Unités : services, timers, sockets, targets...
Vérifier si systemd est actif
# Vérifier le PID 1
ps -p 1 -o comm=
# Doit afficher : systemd
# Version
systemctl --version
Gestion d'un service
# Démarrer un service
sudo systemctl start nginx.service
# Arrêter un service
sudo systemctl stop nginx.service
# Redémarrer (arrêt + démarrage)
sudo systemctl restart nginx.service
# Recharger la configuration (sans arrêt)
sudo systemctl reload nginx.service
# Vérifier l'état
systemctl status nginx.service
Démarrage automatique
# Activer au boot
sudo systemctl enable nginx.service
# Désactiver au boot
sudo systemctl disable nginx.service
# Activer ET démarrer immédiatement
sudo systemctl enable --now nginx.service
Lister et rechercher
# Lister tous les services
systemctl list-units --type=service
# Services actifs uniquement
systemctl list-units --type=service --state=active
# Services en échec
systemctl list-units --type=service --state=failed
# Rechercher un service
systemctl list-unit-files | grep docker
Après modification d'un fichier .service
sudo systemctl daemon-reload
sudo systemctl restart mon-service.service
.service dans /etc/systemd/system/.Étape 1 : Créer le fichier de service
sudo nano /etc/systemd/system/mon-app.service
Étape 2 : Structure du fichier
[Unit]
Description=Mon Application Python
After=network.target
[Service]
Type=simple
User=www-data
Group=www-data
WorkingDirectory=/opt/mon-app
ExecStart=/opt/mon-app/venv/bin/python app.py
Restart=on-failure
RestartSec=5
# Sécurité
NoNewPrivileges=true
PrivateTmp=true
[Install]
WantedBy=multi-user.target
Étape 3 : Activer et démarrer
# Recharger la configuration
sudo systemctl daemon-reload
# Activer au démarrage
sudo systemctl enable mon-app.service
# Démarrer
sudo systemctl start mon-app.service
# Vérifier
systemctl status mon-app.service
Sections expliquées
| Section | Rôle |
|---|---|
| [Unit] | Métadonnées, description, dépendances |
| [Service] | Comment exécuter le service |
| [Install] | Quand démarrer (target) |
Comparaison
| Commande | Action | Effet immédiat | Au reboot |
|---|---|---|---|
start |
Démarre le service | ✅ Oui | ❌ Non |
stop |
Arrête le service | ✅ Oui | ❌ Non |
restart |
Arrête puis redémarre | ✅ Oui | ❌ Non |
reload |
Recharge la config | ✅ Oui (sans interruption) | ❌ Non |
enable |
Active au boot | ❌ Non | ✅ Oui |
disable |
Désactive au boot | ❌ Non | ✅ Oui |
Cas d'usage
# Je veux démarrer un service maintenant
sudo systemctl start nginx
# Je veux qu'il démarre automatiquement au boot
sudo systemctl enable nginx
# Je veux les deux en même temps
sudo systemctl enable --now nginx
# J'ai modifié la config de nginx, je veux recharger sans couper le service
sudo systemctl reload nginx
# Le service est planté, je veux le relancer
sudo systemctl restart nginx
Attention
reload ne fonctionne que si le service le supporte (Nginx, Apache, Postfix...). Sinon, utilisez restart.Étape 1 : Vérifier l'état
systemctl status mon-service.service
Cherchez :Active: failed(rouge)- Le code de sortie (
status=1/FAILURE) - Les dernières lignes de log
Étape 2 : Consulter les logs complets
# Logs du service
journalctl -u mon-service.service
# Logs récents uniquement
journalctl -u mon-service.service -n 50
# Suivre en temps réel
journalctl -u mon-service.service -f
# Uniquement les erreurs
journalctl -u mon-service.service -p err
Étape 3 : Vérifier la syntaxe du fichier service
sudo systemd-analyze verify /etc/systemd/system/mon-service.service
Étape 4 : Tester manuellement
# Exécuter la commande ExecStart à la main
sudo -u www-data /opt/mon-app/venv/bin/python app.py
Erreurs fréquentes
| Symptôme | Cause probable |
|---|---|
code=exited, status=203/EXEC |
Chemin ExecStart invalide |
code=exited, status=217/USER |
Utilisateur inexistant |
code=exited, status=200/CHDIR |
WorkingDirectory inexistant |
code=killed, signal=KILL |
OOM Killer (mémoire) |
Commandes essentielles
# Logs d'un service spécifique
journalctl -u nginx.service
# Les 100 dernières lignes
journalctl -u nginx.service -n 100
# Suivre en temps réel (comme tail -f)
journalctl -u nginx.service -f
# Depuis le dernier boot
journalctl -u nginx.service -b
# Depuis une date
journalctl -u nginx.service --since "2026-01-08 10:00"
# Entre deux dates
journalctl -u nginx.service --since yesterday --until today
Filtrer par niveau de gravité
# Erreurs uniquement
journalctl -u nginx.service -p err
# Erreurs et warnings
journalctl -u nginx.service -p warning
# Niveaux : emerg, alert, crit, err, warning, notice, info, debug
Format de sortie
# Format JSON (pour parsing)
journalctl -u nginx.service -o json
# Format court (une ligne par entrée)
journalctl -u nginx.service -o short
# Avec horodatage précis
journalctl -u nginx.service -o short-precise
Gestion de l'espace disque
# Taille des logs
journalctl --disk-usage
# Nettoyer (garder 7 jours)
sudo journalctl --vacuum-time=7d
# Nettoyer (garder 500 Mo max)
sudo journalctl --vacuum-size=500M
Targets courants
| Target | Équivalent | Description |
|---|---|---|
poweroff.target |
runlevel 0 | Arrêt du système |
rescue.target |
runlevel 1 | Mode maintenance (mono-utilisateur) |
multi-user.target |
runlevel 3 | Mode multi-utilisateur (sans GUI) |
graphical.target |
runlevel 5 | Mode graphique (avec GUI) |
reboot.target |
runlevel 6 | Redémarrage |
Commandes
# Voir le target actuel
systemctl get-default
# Changer le target par défaut (serveur sans GUI)
sudo systemctl set-default multi-user.target
# Changer le target par défaut (desktop avec GUI)
sudo systemctl set-default graphical.target
# Basculer immédiatement vers un target
sudo systemctl isolate rescue.target
Dans un fichier .service
[Install]
WantedBy=multi-user.target
Signifie : "Ce service sera démarré quand le système atteint le mode multi-utilisateur."mask) est plus strict que le désactiver (disable).Différence mask vs disable
| Action | Effet |
|---|---|
disable |
Le service ne démarre pas automatiquement au boot, mais peut être démarré manuellement |
mask |
Le service est complètement bloqué, impossible de le démarrer même manuellement |
Commandes
# Masquer un service
sudo systemctl mask dangerous-service.service
# Vérifier (affiche "masked")
systemctl status dangerous-service.service
# Essayer de démarrer (échouera)
sudo systemctl start dangerous-service.service
# Erreur: Unit dangerous-service.service is masked.
# Démasquer
sudo systemctl unmask dangerous-service.service
Cas d'usage
- Empêcher un service vulnérable de démarrer accidentellement
- Désactiver des services par défaut non souhaités (cups, avahi...)
- Conflits entre services incompatibles
Comment ça marche
mask crée un lien symbolique vers /dev/null, rendant le service inutilisable.Dans le fichier .service
[Service]
# Limite mémoire (max 512 Mo)
MemoryMax=512M
MemoryHigh=400M # Throttling au-delà
# Limite CPU (50% d'un cœur)
CPUQuota=50%
# Nombre de processus max
TasksMax=100
# Priorité I/O (entre 100 et 10000)
IOWeight=200
Appliquer temporairement (sans modifier le fichier)
# Limiter la mémoire à 256 Mo
sudo systemctl set-property mon-service.service MemoryMax=256M
# Limiter le CPU à 25%
sudo systemctl set-property mon-service.service CPUQuota=25%
Vérifier les limites actuelles
systemctl show mon-service.service | grep -E 'Memory|CPU|Tasks'
Exemple complet (service gourmand)
[Service]
ExecStart=/opt/app/run.sh
# Limites strictes
MemoryMax=1G
MemoryHigh=800M
CPUQuota=200% # 2 cœurs max
TasksMax=50
# Tuer si dépassement mémoire
OOMPolicy=kill
Options de sécurité recommandées
[Service]
# Exécuter en tant qu'utilisateur non-root
User=www-data
Group=www-data
# Empêcher l'élévation de privilèges
NoNewPrivileges=true
# Système de fichiers en lecture seule
ProtectSystem=strict
ProtectHome=true
# Répertoire /tmp privé
PrivateTmp=true
# Masquer /proc et /sys
ProtectKernelTunables=true
ProtectKernelModules=true
ProtectControlGroups=true
# Filtrer les appels système
SystemCallFilter=@system-service
SystemCallArchitectures=native
# Réseau restreint (si pas besoin)
PrivateNetwork=true
# Capabilities limitées
CapabilityBoundingSet=CAP_NET_BIND_SERVICE
AmbientCapabilities=CAP_NET_BIND_SERVICE
Analyser la sécurité d'un service
# Score de sécurité (0-10, plus bas = mieux)
systemd-analyze security mon-service.service
Exemple minimal sécurisé
[Unit]
Description=API Sécurisée
After=network.target
[Service]
Type=simple
User=api-user
ExecStart=/opt/api/run
Restart=on-failure
# Durcissement
NoNewPrivileges=true
PrivateTmp=true
ProtectSystem=strict
ProtectHome=true
ReadWritePaths=/var/lib/api
[Install]
WantedBy=multi-user.target
Temps total de démarrage
systemd-analyze
# Startup finished in 3.5s (kernel) + 12.4s (userspace) = 15.9s
Services les plus lents
systemd-analyze blame
# 8.123s apt-daily-upgrade.service
# 4.567s docker.service
# 2.345s NetworkManager-wait-online.service
# ...
Graphique de démarrage (SVG)
systemd-analyze plot > boot.svg
firefox boot.svg # Visualiser
Chaîne critique (dépendances)
systemd-analyze critical-chain
# graphical.target @15.9s
# └─multi-user.target @15.9s
# └─docker.service @11.3s +4.5s
# └─network.target @11.2s
Optimisations courantes
| Service lent | Solution |
|---|---|
apt-daily-upgrade.service |
Décaler avec timer |
NetworkManager-wait-online |
Désactiver si IP statique |
docker.service |
Démarrer à la demande (socket) |
snapd.service |
Désactiver si non utilisé |
Configuration dans le fichier .service
[Service]
ExecStart=/opt/app/run
# Redémarrer en cas d'échec
Restart=on-failure
# Délai entre les redémarrages (éviter boucle infinie)
RestartSec=5
# Nombre max de redémarrages par intervalle
StartLimitBurst=5
StartLimitIntervalSec=60
# → Max 5 redémarrages par minute, sinon abandon
Options de Restart
| Valeur | Redémarre si... |
|---|---|
no |
Jamais (défaut) |
on-success |
Code de sortie = 0 |
on-failure |
Code ≠ 0, signal, timeout |
on-abnormal |
Signal, timeout, watchdog |
on-abort |
Signal non-catchable (SIGKILL) |
always |
Toujours (sauf systemctl stop) |
Exemple robuste
[Service]
ExecStart=/opt/api/server
Restart=always
RestartSec=10
# Attendre 30s avant de considérer le service comme "démarré"
# (évite les redémarrages si crash immédiat)
StartLimitBurst=3
StartLimitIntervalSec=300
# Watchdog : tuer si pas de réponse en 30s
WatchdogSec=30
Vérifier le comportement
# Tuer le processus pour tester le redémarrage
sudo kill -9 $(pgrep -f mon-app)
systemctl status mon-app.service
Créer un timer
1. Le service (ce qui sera exécuté)# /etc/systemd/system/backup.service
[Unit]
Description=Backup quotidien
[Service]
Type=oneshot
ExecStart=/opt/scripts/backup.sh
User=backup
2. Le timer (quand exécuter)# /etc/systemd/system/backup.timer
[Unit]
Description=Timer pour backup quotidien
[Timer]
# Tous les jours à 3h du matin
OnCalendar=*-*-* 03:00:00
# Rattraper si le système était éteint
Persistent=true
# Ajouter un délai aléatoire (évite surcharge simultanée)
RandomizedDelaySec=300
[Install]
WantedBy=timers.target
Activer le timer
sudo systemctl daemon-reload
sudo systemctl enable --now backup.timer
Syntaxe OnCalendar
# Tous les jours à minuit
OnCalendar=daily
# Toutes les heures
OnCalendar=hourly
# Tous les lundis à 8h
OnCalendar=Mon *-*-* 08:00:00
# Toutes les 15 minutes
OnCalendar=*:0/15
Lister les timers actifs
systemctl list-timers
Types principaux
| Type | Comportement | Exemple |
|---|---|---|
simple |
Le processus ExecStart est le service | Scripts, apps Node.js |
forking |
Le processus se fork, le parent quitte | Apache, Nginx traditionnel |
oneshot |
Exécute une fois et termine | Scripts de maintenance |
notify |
Le service signale quand il est prêt | systemd-notify, Docker |
dbus |
Prêt quand nom D-Bus acquis | Services desktop |
idle |
Attend que les jobs soient finis | Login prompts |
Exemples
simple (défaut, le plus courant) :[Service]
Type=simple
ExecStart=/usr/bin/node /opt/app/server.js
forking (daemons traditionnels) :[Service]
Type=forking
PIDFile=/var/run/nginx.pid
ExecStart=/usr/sbin/nginx
ExecReload=/bin/kill -HUP $MAINPID
oneshot (scripts ponctuels) :[Service]
Type=oneshot
ExecStart=/opt/scripts/cleanup.sh
RemainAfterExit=yes # Garder l'état "active"
notify (signal de disponibilité) :[Service]
Type=notify
ExecStart=/usr/bin/docker daemon
[Unit].Directives principales
| Directive | Signification |
|---|---|
After= |
Démarrer après ce service (ordre) |
Before= |
Démarrer avant ce service |
Requires= |
Dépendance forte (si l'autre plante, celui-ci aussi) |
Wants= |
Dépendance souple (si l'autre plante, continue) |
BindsTo= |
Dépendance très forte (arrêt synchronisé) |
Conflicts= |
Ne peut pas tourner en même temps |
Exemples
API qui a besoin de la base de données :[Unit]
Description=Mon API
After=network.target postgresql.service
Requires=postgresql.service
# Si PostgreSQL plante, l'API est arrêtée aussi
Service optionnel (Redis comme cache) :[Unit]
Description=Mon API avec cache optionnel
After=network.target redis.service
Wants=redis.service
# Si Redis n'est pas là, l'API démarre quand même
Services incompatibles :[Unit]
Description=Apache
Conflicts=nginx.service
# Apache et Nginx ne peuvent pas tourner ensemble
Visualiser les dépendances
# Dépendances d'un service
systemctl list-dependencies nginx.service
# Dépendances inversées (qui dépend de...)
systemctl list-dependencies --reverse network.target