Cours Linux / Reproduire une panne et vérifier la restauration du service
Pour apprendre à réparer une panne Linux, établissez d’abord une réponse normale sur une machine de pratique, modifiez une seule condition, recueillez l’état du service et ses journaux, puis rétablissez la configuration sauvegardée. La réparation n’est confirmée que lorsque le service fonctionne et que le client reçoit à nouveau la réponse attendue.
Cet atelier utilise un service systemd utilisateur et le serveur HTTP simple de Python, uniquement sur 127.0.0.1. Préparez la VM, son instantané et sa console, puis la méthode du cours de diagnostic par les journaux. Les commandes visent une VM Ubuntu 26.04 LTS ou Rocky Linux 9 avec Python 3, curl et un gestionnaire systemd --user actif. Ne faites pas cet exercice sur le Nginx, SSH, pare-feu ou disque d’un serveur de production.
Préparer un service isolé et sa réponse normale
Vérifiez systemctl --user status, le chemin de Python avec command -v python3 et l’absence d’écoute sur le port de pratique avec ss -lnt. L’exemple utilise 18080 : si ce port est pris, choisissez un port libre et remplacez toutes ses occurrences dans l’unité et les requêtes. http.server n’est pas destiné à la production ; son manuel Python signale ses contrôles de sécurité limités. La liaison à l’adresse de boucle locale évite l’exposition réseau de cet atelier.
Dans le même terminal, créez le dossier et l’unité seulement si les noms sont libres. Le code refuse d’écraser $HOME/linux-recovery-lab-fr ou linux-course-recovery-fr.service. Si l’un existe, choisissez de nouveaux noms cohérents avant de poursuivre. Le chemin absolu de Python est inscrit dans l’unité d’après la machine, au lieu de supposer /usr/bin/python3.
lab="$HOME/linux-recovery-lab-fr"
unit="$HOME/.config/systemd/user/linux-course-recovery-fr.service"
python_bin=$(command -v python3) || exit 1
[[ "$python_bin" = /* ]] || exit 1
if [[ -e "$lab" || -L "$lab" || -e "$unit" || -L "$unit" ]]; then
printf 'Dossier ou unité déjà présent : choisir un autre nom\n' >&2
else
mkdir -p -- "$HOME/.config/systemd/user" || exit 1
mkdir -m 700 -- "$lab" "$lab/site" || exit 1
printf 'réponse normale\n' > "$lab/site/index.html" || exit 1
cat > "$unit" <<EOF
[Unit]
Description=Atelier isolé de reprise Linux
[Service]
Type=simple
WorkingDirectory=%h/linux-recovery-lab-fr/site
ExecStart=$python_bin -m http.server 18080 --bind 127.0.0.1
EOF
cat -- "$unit"
fi
Si le dossier ou l’unité n’a été créé qu’en partie, inspectez ce qui existe et réparez cet atelier avant toute nouvelle tentative ; ne forcez pas l’écrasement. Vérifiez que WorkingDirectory et le chemin Python correspondent à votre VM. Le service n’est pas activé au démarrage, donc cet exercice ne crée pas de démarrage automatique.
Chargez l’unité puis vérifiez son état et la page. Gardez le port identique dans toutes les commandes. Quand les deux contrôles réussissent, conservez une copie du fichier d’unité dans le dossier créé pour cet atelier :
systemctl --user daemon-reload
systemctl --user start linux-course-recovery-fr.service
systemctl --user is-active linux-course-recovery-fr.service
curl --fail --max-time 5 http://127.0.0.1:18080/
cp -- "$HOME/.config/systemd/user/linux-course-recovery-fr.service" "$HOME/linux-recovery-lab-fr/service.good"
Attendez active et « réponse normale ». Si l’un échoue, n’injectez pas encore de panne : inspectez le port, les journaux utilisateur, le chemin de Python et la syntaxe de l’unité. service.good doit représenter une configuration qui vient réellement de fonctionner ; la simple copie d’un fichier non vérifié ne fournirait pas un point de restauration fiable.
Expérience 1 : rendre le chemin d’exécution invalide
Ne poursuivez que si service.good existe et que l’unité active sert la page. Lisez la ligne ExecStart= actuelle, puis remplacez cette ligne dans cette seule unité de pratique par un programme inexistant. La modification de l’unité est volontaire ; restart peut lui-même retourner une erreur attendue. Relevez l’heure et le code de sortie avant de consulter l’état et les journaux.
unit="$HOME/.config/systemd/user/linux-course-recovery-fr.service"
grep '^ExecStart=' "$unit"
sed -i 's@^ExecStart=.*$@ExecStart=/nonexistent/course-python -m http.server 18080 --bind 127.0.0.1@' "$unit"
grep '^ExecStart=' "$unit"
systemctl --user daemon-reload
systemctl --user restart linux-course-recovery-fr.service
systemctl --user status linux-course-recovery-fr.service --no-pager
journalctl --user -u linux-course-recovery-fr.service --since '5 minutes ago' --no-pager
Le processus n’existe pas, donc l’unité ne doit pas rester active. Selon le moment, l’échec apparaît dès restart ou dans l’état consulté ensuite. Comparez le journal à la seule ligne changée : vous devriez voir un échec d’exécution, souvent associé à 203/EXEC dans systemd ; le message exact dépend de la version et du contexte. Le manuel systemd.exec définit les codes d’échec des étapes de lancement. Ce signe oriente vers le programme de démarrage, pas directement vers un pare-feu.
Restaurer l’unité et refaire la même requête
Après avoir conservé le journal pertinent, recopiez uniquement service.good vers l’unité de cet atelier. Rechargez les unités, réinitialisez l’état d’échec de cette unité si nécessaire, puis démarrez-la et répétez les deux contrôles du début :
cp -- "$HOME/linux-recovery-lab-fr/service.good" "$HOME/.config/systemd/user/linux-course-recovery-fr.service"
systemctl --user daemon-reload
systemctl --user reset-failed linux-course-recovery-fr.service
systemctl --user start linux-course-recovery-fr.service
systemctl --user is-active linux-course-recovery-fr.service
curl --fail --max-time 5 http://127.0.0.1:18080/
reset-failed remet à zéro l’état et certains compteurs de démarrage, mais ne corrige pas une mauvaise unité : c’est le fichier sauvegardé qui restaure le chemin valide. La réussite demande encore active et « réponse normale » depuis le même URL. Si le retour échoue, lisez l’état et le journal actualisés au lieu de multiplier les modifications.
Expérience 2 : distinguer HTTP 404 et port fermé
Une réponse HTTP 404 signifie que la requête a atteint un serveur qui ne possède pas le chemin demandé. Après l’arrêt du service, une requête sur le même port teste une autre couche : il n’y a plus de processus à l’écoute et curl devrait signaler une erreur de connexion. Procédez dans cet ordre, puis redémarrez le service :
curl -i --max-time 5 http://127.0.0.1:18080/missing-resource
systemctl --user stop linux-course-recovery-fr.service
curl -i --connect-timeout 2 --max-time 5 http://127.0.0.1:18080/
ss -lnt
systemctl --user start linux-course-recovery-fr.service
curl --fail --max-time 5 http://127.0.0.1:18080/
La première commande affiche normalement HTTP 404 ; sans --fail, curl peut néanmoins terminer avec le code de sortie 0 pour cette réponse HTTP. Après l’arrêt, une erreur de connexion et l’absence de l’écoute sur 18080 distinguent le transport d’une réponse 404. Si une autre application s’est mise à écouter sur ce port, l’hypothèse change : inspectez le processus avant de conclure. La dernière requête doit de nouveau afficher la page de base. Le manuel de curl distingue les erreurs de transfert des codes HTTP.
Noter les preuves et décider si le rétablissement est terminé
| Étape | Preuve attendue dans cet atelier |
|---|---|
| Référence | Unité active, écoute sur 127.0.0.1:18080 et texte de la page. |
| Changement unique | Ligne ExecStart invalide, puis, dans une autre expérience, arrêt du service. |
| Symptôme | État et journal d’échec ; séparément HTTP 404 ou refus de connexion. |
| Réparation | Restauration de service.good ou redémarrage du service arrêté. |
| Nouvel essai | Même URL et réponse « réponse normale », avec unité active. |
| Prévention | Contrôle du chemin exécutable et de l’unité avant déploiement, surveillance de la réponse. |
Consignez l’heure, le changement précis, le message réellement observé et le résultat de la même requête avant/après. Une coïncidence ne suffit pas : la panne doit correspondre au changement et disparaître après la réparation. Ici, un service active sans bonne réponse client ne suffit pas. Inversement, une ancienne réponse en cache ne prouverait pas que le bon processus sert le nouveau contenu.
Ne remplissez pas le disque, ne bloquez pas SSH et ne supprimez pas au hasard des fichiers pour « enrichir » ce laboratoire. Ces expériences demanderaient une VM clonée, un disque limité, une console et des sauvegardes vérifiées. Le but est de répéter la chaîne observation → hypothèse → changement ciblé → nouvelle vérification sans perdre la voie de récupération.
Arrêter et ranger uniquement les éléments créés
Confirmez que vous êtes sur le compte de pratique et que le nom de l’unité est bien celui créé au début. Arrêtez cette seule unité, vérifiez le fichier que vous allez retirer, puis rechargez systemd après suppression :
systemctl --user stop linux-course-recovery-fr.service
systemctl --user reset-failed linux-course-recovery-fr.service
unit="$HOME/.config/systemd/user/linux-course-recovery-fr.service"
ls -l -- "$unit"
rm -- "$unit"
systemctl --user daemon-reload
ss -lnt
Le port 18080 ne doit plus être écouté par ce service. Le dossier $HOME/linux-recovery-lab-fr contient encore service.good et la page d’essai : vérifiez son contenu et retirez-le avec le gestionnaire de fichiers lorsque vous n’en avez plus besoin. Ne touchez pas aux autres unités utilisateur ni à leurs journaux. Si vous avez choisi d’autres noms ou un autre port, adaptez la vérification et la suppression aux éléments effectivement créés.




