Mécanismes OS lors du redémarrage
Suivre un redémarrage pas à pas : de systemctl reboot au retour de default.target
Un redémarrage Linux est une chaîne d'étapes ordonnées : arrêter les services dans l'ordre inverse de leurs dépendances, écrire sur le disque ce qui reste en mémoire, démonter, redémarrer le matériel, puis remonter du firmware au noyau et jusqu'à systemd ; chaque étape protège la cohérence des données.
Objectifs
- Décrire, dans l'ordre, les étapes de l'arrêt d'un système Linux géré par systemd.
- Expliquer le rôle du cache de pages, de la synchronisation disque (
sync,fsync) et de la journalisation du système de fichiers. - Décrire la chaîne de démarrage : firmware BIOS ou UEFI, chargeur d'amorçage, noyau et initramfs, PID 1.
- Observer chaque étape avec les outils standard :
systemctl,journalctl,systemd-analyze,efibootmgr.
Vue d'ensemble
On suit une seule machine : le serveur de la bibliothèque numérique d'un lycée de Kumasi, sous Debian, sur lequel Ama tape systemctl reboot. On avance étape par étape ; chaque étape ne commence que lorsque la précédente est terminée.
flowchart LR A[systemctl reboot] --> B[Arret des services] B --> C[Ecriture du cache] C --> D[Demontage des disques] D --> E[Appel reboot au noyau] E --> F[Firmware UEFI ou BIOS] F --> G[Chargeur GRUB] G --> H[Noyau et initramfs] H --> I[systemd PID 1] I --> J[default target]
Partie 1 — La séquence d'arrêt
Étape 1 : systemd reçoit la demande et vise reboot.target
systemctl reboot demande à systemd (le processus de PID 1) d'activer l'unité cible reboot.target. Les unités de service ont par défaut une dépendance Conflicts=shutdown.target : activer la cible d'arrêt implique donc d'arrêter ces services. On peut voir ce que la cible entraîne avec systemctl list-dependencies reboot.target.
Étape 2 : arrêt des services dans l'ordre inverse du démarrage
Si le service web est déclaré After=postgresql.service (il démarre après la base), alors à l'arrêt systemd l'arrête avant la base : l'ordre d'arrêt est l'inverse de l'ordre de démarrage. Ainsi, la base ne disparaît pas sous les pieds de l'application qui lui écrit encore.
Pour chaque service, systemd :
- exécute la commande
ExecStop=si elle existe ; - envoie le signal
SIGTERM(réglable parKillSignal=) : le programme doit terminer ses transactions et fermer ses fichiers ; - attend au plus
TimeoutStopSec=(par défaut 90 secondes, valeur réglée parDefaultTimeoutStopSec=dans/etc/systemd/system.conf) ; - envoie
SIGKILLaux processus restants : ils meurent sans pouvoir rien enregistrer.
Étape 3 : écriture des données en attente (synchronisation)
Les pages modifiées mais pas encore écrites s'appellent des pages sales (dirty pages). Le noyau les écrit périodiquement ; deux réglages en donnent le rythme :
vm.dirty_writeback_centisecs(par défaut 500, soit 5 s) : intervalle de réveil des fils d'écriture ;vm.dirty_expire_centisecs(par défaut 3000, soit 30 s) : âge à partir duquel une page sale doit être écrite.
Un programme qui veut une garantie appelle fsync() sur son fichier : l'appel ne rend la main qu'une fois les données sur le disque. C'est ce que font les bases de données à chaque validation de transaction. À l'arrêt, systemd et le noyau forcent l'écriture de tout le cache (l'équivalent de la commande sync).
Ordre de grandeur : un programme qui écrit sans fsync() à \(r = 20\) Mo/s peut avoir jusqu'à environ
de données seulement en mémoire, dans la limite fixée par vm.dirty_ratio et vm.dirty_background_ratio (part de la mémoire au-delà de laquelle l'écriture est accélérée ou imposée). C'est ce volume qu'une coupure de courant peut faire perdre.
Étape 4 : démontage des systèmes de fichiers
Une fois les processus arrêtés, systemd démonte les systèmes de fichiers (unités .mount) et désactive le swap. Le système de fichiers racine, encore utilisé, est remonté en lecture seule. Un ext4 démonté proprement est marqué « propre » : au prochain démarrage, aucune vérification longue n'est nécessaire.
Étape 5 : systemd-shutdown et l'appel système reboot()
En fin de parcours, PID 1 se remplace par le programme systemd-shutdown, qui tue les derniers processus, tente de démonter ou remonter en lecture seule ce qui reste, détache les volumes (boucles, RAID logiciel, chiffrement), puis appelle l'appel système reboot() avec la commande de redémarrage. Le noyau arrête les périphériques et demande au matériel de repartir.
Le service web.service est déclaré After=postgresql.service. Que fait systemd au redémarrage ?
Partie 2 — La séquence de démarrage
Étape 6 : le firmware (BIOS ou UEFI)
Le firmware effectue l'auto-test (POST) et initialise le matériel, puis cherche un programme d'amorçage :
- BIOS (ancien mode) : il lit le premier secteur du disque, le MBR (512 octets, dont 446 de code d'amorçage), et lui passe la main.
- UEFI : il consulte ses entrées de démarrage enregistrées en mémoire non volatile et lance un fichier
.efisitué sur la partition système EFI (ESP, formatée en FAT). Sous Linux,efibootmgr -vliste ces entrées et leur ordre.
Étape 7 : le chargeur d'amorçage
GRUB (ou systemd-boot) affiche éventuellement un menu, charge en mémoire l'image du noyau (vmlinuz) et l'image initiale initramfs, et transmet au noyau sa ligne de commande (par exemple root=UUID=… pour désigner la partition racine). On la relit après démarrage dans /proc/cmdline.
Étape 8 : le noyau et l'initramfs
Le noyau s'initialise (mémoire, ordonnanceur, pilotes intégrés), puis exécute l'initramfs : un petit système de fichiers en mémoire qui contient les pilotes et outils nécessaires pour trouver la vraie racine (pilote de contrôleur disque, déchiffrement LUKS, LVM, RAID). Si le système de fichiers n'a pas été démonté proprement, c'est ici ou juste après que le journal est rejoué ou que fsck est lancé. Ensuite, la racine réelle est montée et l'on bascule dessus.
Étape 9 : systemd, PID 1, jusqu'à default.target
Le noyau lance /sbin/init, qui est systemd sur la plupart des distributions actuelles. systemd lit les unités, calcule les dépendances (Requires=, Wants=, After=), démarre en parallèle tout ce qui peut l'être et vise default.target (souvent multi-user.target sur un serveur, graphical.target sur un poste de travail ; systemctl get-default l'affiche).
Après un redémarrage, la machine s'arrête sur une invite de l'initramfs indiquant que la racine est introuvable. Quelle étape est en cause ?
Partie 3 — Exemples résolus
Exemple 1 — Pourquoi l'arrêt a-t-il pris 90 secondes ?
Au service informatique d'une mairie à Niamey, chaque redémarrage affiche « A stop job is running for collecteur.service (1min 30s) ». Analyse la situation.
journalctl -b -1 -u collecteur.service. On y voit « State 'stop-sigterm' timed out. Killing. » : le service n'a pas réagi au SIGTERM.TimeoutStopSec par défaut de 90 s. systemd a attendu tout le délai, puis envoyé SIGKILL.systemctl edit collecteur.service, avec TimeoutStopSec=20s) ne fait que raccourcir l'attente, sans protéger les données.Exemple 2 — Mesurer le démarrage
Après le redémarrage, Ama veut savoir combien de temps a pris chaque phase et quel service ralentit le démarrage. Quelles commandes, et comment lire le résultat ? Cherche d'abord.
Voir la solution
systemd-analyze affiche le temps passé dans le firmware, le chargeur, le noyau, l'initramfs et l'espace utilisateur, par exemple « Startup finished in 4.1s (firmware) + 2.0s (loader) + 1.8s (kernel) + 3.2s (initrd) + 12.5s (userspace) ». Le total est la somme :
L'espace utilisateur pèse le plus lourd (\(12{,}5 / 23{,}6 \approx 53\,\%\)). systemd-analyze blame classe les services par durée de démarrage ; systemd-analyze critical-chain montre la chaîne de dépendances qui retarde réellement default.target (un service lent mais hors de cette chaîne ne retarde rien, car il démarre en parallèle).
Exemple 3 — Coupure de courant pendant une écriture
Pendant un délestage, le serveur s'éteint brutalement alors qu'un script copiait des fichiers sans fsync(), et que PostgreSQL validait des transactions. Que retrouve-t-on au redémarrage ?
Voir la solution
Aucune des étapes 2 à 5 n'a eu lieu. Au montage, ext4 rejoue son journal : la structure du système de fichiers est cohérente. Les fichiers copiés depuis moins d'environ 30 s peuvent être vides, tronqués ou absents, car leurs données étaient encore dans le cache. PostgreSQL, qui fait un fsync() de son journal d'écriture anticipée (WAL) à chaque validation, rejoue ce journal au démarrage : les transactions validées sont conservées, celles en cours sont annulées. Leçon : la cohérence vient de la combinaison « journal du système de fichiers + fsync de l'application ».
Erreurs fréquentes
- Croire que « écrit » veut dire « sur le disque » : sans
fsync()nisync, les données peuvent rester en mémoire plusieurs secondes. - Croire que le journal ext4 protège le contenu des fichiers : en mode
data=ordered, il protège la structure, pas les données non synchronisées. - Confondre ordre et dépendance :
After=fixe l'ordre,Requires=ouWants=fixent le besoin. Un service avecRequires=mais sansAfter=peut démarrer en même temps que ce dont il dépend. - Confondre BIOS et UEFI : le MBR et ses 446 octets de code concernent l'amorçage BIOS ; en UEFI, on lance un fichier
.efide la partition ESP. - Lire le mauvais journal : pour comprendre un arrêt, il faut le démarrage précédent,
journalctl -b -1, et nonjournalctl -b.
Récapitulatif
systemctl rebootactivereboot.target.- Les services s'arrêtent dans l'ordre inverse du démarrage :
ExecStop, SIGTERM, attente (90 s par défaut), SIGKILL. - Le cache de pages est écrit sur le disque ; les applications sérieuses ont déjà fait
fsync(). - Les systèmes de fichiers sont démontés, la racine remontée en lecture seule.
systemd-shutdownappellereboot().- Firmware (POST, BIOS/MBR ou UEFI/ESP) → GRUB → noyau + initramfs → montage de la racine → systemd (PID 1) →
default.target.
Quelle commande montre la chaîne de dépendances qui a réellement retardé l'arrivée à default.target ?
Teste tes connaissances sur ce cours
Crée ton compte gratuitement pour accéder aux quiz associés et suivre ta progression.
