Passer au contenu principal
Linux, OS

systemd vs SysVinit : comprendre le boot et la gestion des services sous Debian

Pendant longtemps, de nombreux systèmes Unix et GNU/Linux ont démarré leurs services selon le modèle System V init, ou SysVinit : des runlevels, des scripts shell et une collection méthodiquement organisée de liens symboliques.

Puis systemd est arrivé avec une autre philosophie : décrire les services et leurs relations sous forme d’unités, construire un graphe de dépendances et lancer en parallèle ce qui peut l’être. Le changement a apporté des possibilités importantes, quelques commandes très pratiques et suffisamment de débats pour assurer plusieurs décennies d’archives sur les forums Linux.

Sous Debian, systemd est le système d’init par défaut depuis Debian 8 “Jessie”. SysVinit reste historiquement important à comprendre, notamment parce que son organisation explique encore beaucoup de conventions Unix actuelles.

À quoi sert un système d’init ?

Après le firmware, le chargeur d’amorçage et le noyau Linux, le système doit lancer l’espace utilisateur. Le noyau démarre alors le programme d’init, qui devient le processus PID 1.

Sur une Debian moderne utilisant systemd, vous pouvez le vérifier avec :

ps -p 1 -o pid,comm,args

Vous verrez normalement systemd comme processus 1.

Le rôle d’un système d’init dépasse largement « lancer quelques programmes ». Il doit notamment orchestrer le démarrage et l’arrêt des services, gérer leurs dépendances, surveiller certains processus et organiser les différents états du système.

Avec systemd, cette responsabilité s’étend également à des mécanismes tels que les sockets, timers, montages, automounts, cgroups et diverses ressources système.

SysVinit : scripts, runlevels et liens symboliques

Le modèle SysVinit repose principalement sur des scripts situés dans :

/etc/init.d/

Un service traditionnel possède par exemple un script capable de recevoir différentes actions :

/etc/init.d/apache2 start
/etc/init.d/apache2 stop
/etc/init.d/apache2 restart
/etc/init.d/apache2 status

Le système utilise ensuite des runlevels, c’est-à-dire différents états globaux définissant quels services doivent être actifs.

Des répertoires comme :

/etc/rc0.d/
/etc/rc1.d/
/etc/rc2.d/
/etc/rc3.d/
/etc/rc4.d/
/etc/rc5.d/
/etc/rc6.d/

contiennent historiquement des liens vers les scripts de `/etc/init.d/`. Leur nom indiquait notamment si le service devait être démarré ou arrêté et contribuait à déterminer l’ordre d’exécution.

On pouvait rencontrer des noms ressemblant à :

S01service-a
S02service-b
K01service-c

Le modèle est relativement facile à comprendre : ce sont essentiellement des scripts exécutés selon une organisation prédéfinie.

Il serait néanmoins incorrect de considérer SysVinit comme entièrement dépourvu de gestion des dépendances. Debian a utilisé des informations de dépendance et des outils autour des scripts d’init afin d’en déterminer l’ordre. Le modèle reste cependant beaucoup plus procédural que celui de systemd.

systemd : unités et graphe de dépendances

systemd remplace l’idée « exécuter ces scripts dans cet ordre » par une approche largement déclarative. On décrit ce qu’est une ressource, de quoi elle dépend et quand elle doit être disponible.

Ces objets sont appelés des units.

Extension Rôle
.service Processus ou service
.socket Socket pouvant déclencher un service
.target Groupe d’unités et point de synchronisation
.timer Activation planifiée, comparable dans certains usages à cron
.mount Point de montage
.automount Montage à la demande
.path Activation liée à un chemin du système de fichiers
.device Périphérique
.slice Organisation de ressources via les cgroups

Les fichiers fournis par les paquets se trouvent principalement dans les répertoires système prévus par la distribution, notamment `/usr/lib/systemd/system/`. Les personnalisations permanentes de l’administrateur vont normalement dans :

/etc/systemd/system/

et les unités ou modifications temporaires peuvent apparaître sous :

/run/systemd/system/

La configuration de `/etc` possède une priorité élevée et permet donc de personnaliser un service sans modifier directement le fichier installé par le paquet.

Les dépendances

Une unité peut déclarer des relations telles que :

Wants=
Requires=
Before=
After=

Il faut distinguer dépendance et ordre. Par exemple, `Requires=` exprime une relation de dépendance, tandis que `After=` impose un ordre de démarrage. Une unité peut parfaitement dépendre d’une autre sans que toutes leurs relations temporelles soient implicites dans les deux sens.

systemd construit alors un graphe et peut démarrer simultanément les services qui ne sont pas obligés de s’attendre.

Cette parallélisation peut accélérer le boot, mais :

systemd ne garantit pas magiquement qu’un ordinateur démarrera rapidement. Un service qui attend le réseau pendant 90 secondes reste capable de transformer un SSD NVMe en expérience contemplative.

Targets : les descendants plus souples des runlevels

Les .target regroupent différentes unités et servent de points de synchronisation. Ils remplacent en grande partie la logique des runlevels.

Ancien runlevel Équivalent systemd courant
0 poweroff.target
1 rescue.target
2, 3, 4 multi-user.target
5 graphical.target
6 reboot.target

Mais la correspondance reste approximative : SysVinit considère essentiellement un runlevel courant, alors que systemd peut avoir plusieurs targets actifs simultanément.

Pour connaître la cible par défaut :

systemctl get-default

Pour la modifier :

sudo systemctl set-default multi-user.target

ou :

sudo systemctl set-default graphical.target

Pour basculer immédiatement vers une target :

sudo systemctl isolate multi-user.target

Cette dernière commande peut arrêter les unités incompatibles avec la cible choisie ; ce n’est donc pas exactement un bouton décoratif à tester au hasard sur un serveur distant.

Administrer les services avec systemctl et journalctl

systemctl constitue l’interface principale pour contrôler le gestionnaire systemd.

# Démarrer un service
sudo systemctl start nginx

# Arrêter un service
sudo systemctl stop nginx

# Redémarrer
sudo systemctl restart nginx

# Demander au service de recharger sa configuration
sudo systemctl reload nginx

# Voir son état
systemctl status nginx

Il faut particulièrement distinguer start et enable.

sudo systemctl start nginx

démarre nginx maintenant, mais ne signifie pas nécessairement qu’il démarrera automatiquement au prochain boot.

sudo systemctl enable nginx

configure son activation future selon les instructions de la section `[Install]`, mais ne le démarre pas immédiatement.

Pour faire les deux :

sudo systemctl enable --now nginx

De même :

sudo systemctl disable --now nginx

désactive son démarrage automatique et l’arrête immédiatement.

Les journaux

systemd fournit systemd-journald, qui collecte des événements structurés provenant du système et des services.

Quelques commandes particulièrement utiles :

# Journal d'un service
journalctl -u nginx

# Journal du boot actuel
journalctl -b

# Derniers événements d'un service
journalctl -u nginx -n 50

# Suivi en temps réel
journalctl -u nginx -f

# Erreurs du boot actuel
journalctl -b -p err

L’association :

systemctl status service
journalctl -u service

constitue souvent le premier réflexe de diagnostic sous Debian moderne.

Analyser le démarrage

systemd dispose aussi d’outils permettant d’étudier le boot :

systemd-analyze
systemd-analyze blame
systemd-analyze critical-chain

blame indique notamment le temps passé par les unités dans leur phase d’activation, tandis que critical-chain tente de montrer le chemin critique ayant retardé l’atteinte d’une cible.

Il faut interpréter ces résultats avec prudence, car les services fonctionnent souvent en parallèle et certains utilisent l’activation par socket. L’unité affichée avec la plus longue durée n’est donc pas automatiquement « responsable de tout le boot lent ».

Créer ou modifier proprement un service systemd

Une unité de service minimale peut ressembler à ceci :

[Unit]
Description=Application Chapal
After=network.target

[Service]
Type=simple
ExecStart=/usr/local/bin/chapal-service
Restart=on-failure
User=chapal

[Install]
WantedBy=multi-user.target

Pour une unité créée localement, on peut l’enregistrer par exemple sous :

/etc/systemd/system/chapal.service

Après avoir créé ou modifié manuellement un fichier d’unité :

sudo systemctl daemon-reload

puis :

sudo systemctl enable --now chapal.service

daemon-reload demande à systemd de relire ses fichiers d’unités et de reconstruire son graphe de dépendances. Il ne faut pas le confondre avec :

systemctl reload nginx

qui demande à nginx lui-même de recharger sa configuration.

Modifier une unité fournie par un paquet

Il vaut mieux éviter d’éditer directement le fichier installé sous `/usr/lib/systemd/system/`, car une mise à jour du paquet pourrait le remplacer.

Utilisez plutôt :

sudo systemctl edit nginx.service

systemd crée alors un drop-in sous `/etc/systemd/system/`, permettant de surcharger seulement les paramètres nécessaires.

Pour voir l’unité complète avec ses éventuelles surcharges :

systemctl cat nginx.service

systemd contre SysVinit : comparaison sans guerre de religion

Aspect SysVinit systemd
Configuration des services Scripts principalement procéduraux Unités principalement déclaratives
Organisation du boot Runlevels et scripts Targets et graphe de dépendances
Parallélisation Possible avec mécanismes complémentaires Intégrée au modèle de dépendances
Supervision Limitée dans le modèle classique Suivi direct des unités et processus
Logs intégrés Non systemd-journald
Activation par socket Pas une fonction centrale de SysVinit Native
Timers Habituellement cron Unités .timer
Gestion des ressources Externe au modèle d’init Intégration avec les cgroups Linux
Portabilité Concept historiquement répandu sur différents Unix Conçu spécifiquement pour Linux
Complexité Petit cœur, nombreux scripts et outils périphériques Écosystème beaucoup plus large et intégré

Les critiques historiques de systemd concernent notamment son périmètre fonctionnel, sa complexité, son intégration profonde à Linux et la concentration de nombreuses fonctions dans un même projet.

Ses défenseurs mettent en avant une gestion cohérente des dépendances, une supervision plus fiable des processus, les cgroups, l’activation à la demande, les logs structurés et une interface d’administration largement homogène.

Les deux points de vue reposent sur de vraies différences de philosophie. SysVinit privilégie un cœur relativement minimal entouré de scripts ; systemd propose une infrastructure beaucoup plus intégrée.

Conclusion : de l’ordre des scripts au graphe d’unités

SysVinit peut être résumé par :

runlevel → liens rc → scripts /etc/init.d → services

systemd fonctionne davantage comme :

target → dépendances → units → processus et ressources

Le second modèle permet au système de raisonner explicitement sur les relations entre services au lieu de dépendre principalement d’un ordre de scripts déterminé à l’avance.

Pour l’administration quotidienne d’une Debian moderne, les commandes essentielles restent finalement assez raisonnables :

systemctl status service
systemctl start service
systemctl stop service
systemctl restart service
systemctl enable --now service

journalctl -u service
journalctl -b

systemd-analyze
systemd-analyze critical-chain

SysVinit n’était donc pas un dinosaure incapable de gérer autre chose que trois scripts shell attachés avec de la ficelle, et systemd n’est pas davantage un rituel occulte chargé d’exécuter l’intégralité du système d’exploitation.

Ce sont deux générations de conception différentes : l’une largement fondée sur des scripts, des runlevels et un ordre de démarrage ; l’autre sur des unités, des dépendances et une gestion intégrée des ressources.

Et si vous souhaitez savoir lequel provoque le plus de disputes, aucune commande n’est nécessaire.

Un forum Linux suffit.