Mini-test 8

Robustesse

Gerer les erreurs, capturer les sorties, survivre aux pannes

9 questions ciblees

|| et && set -e 2> logs trap

Cliquez Voir la solution sur chaque slide

← → naviguer · I indice · S solution · R recommencer

Question 1 / 9 > ecraser

Capturer un etat instantane dans un fichier

Chaque jour a midi, on veut un fichier /var/log/etat-disque.txt qui contient l'utilisation actuelle du disque (la commande df -h produit ce qu'on veut). Le fichier doit contenir seulement le plus recent : a chaque execution, on ecrase le precedent.

Commande complete :

Le symbole > redirige la sortie vers un fichier en l'ecrasant. Format : commande > fichier.
DF(1) - extrait du manuel
NAME
       df - report file system disk space usage

SYNOPSIS
       df [OPTION...] [FILE...]

DESCRIPTION
       Affiche l'espace disque utilise et disponible sur les systemes de
       fichiers contenant chaque argument FILE (par defaut : tous montes).

OPTIONS
       -h, --human-readable
              tailles lisibles : 1.0K, 2.3M, 5.7G (puissances de 1024)

       -H, --si
              comme -h, mais puissances de 1000 (1.0KB = 1000 octets)

       -T, --print-type
              afficher le type de systeme de fichiers (ext4, xfs...)

       -i, --inodes
              afficher les inodes utilises au lieu des octets

       -a, --all
              inclure les pseudo, dummy, dupliques systemes de fichiers

       --total
              ajouter une ligne de total general

       -x TYPE
              exclure le type de systeme de fichiers TYPE

EXEMPLES
       # Format lisible humain
       df -h

       # Avec type de systeme
       df -hT

       # Inodes au lieu d'octets
       df -i

       # Snapshot dans un fichier (la question Q1 !)
       df -h > /var/log/etat-disque.txt

       # Filtrer un point de montage precis
       df -h /home
df -h > /var/log/etat-disque.txt

Effet :

Variantes :

ps aux > /var/log/processus.txt        # snapshot des process
free -h > /var/log/memoire.txt          # snapshot memoire
systemctl status ircd-hybrid > etat.txt # statut a un instant

Question 2 / 9 >> ajouter

Tenir un journal qui s'accumule

A chaque fois que la sauvegarde se termine, ajouter une ligne datee au journal /var/log/historique-sauvegardes.log sans effacer les precedentes. Le message doit dire "Sauvegarde OK le ..." avec la date du jour.

Exemple de ce que devrait contenir le journal apres 3 jours :

Sauvegarde OK le Mon May 11 02:15:00 EDT 2026 Sauvegarde OK le Tue May 12 02:15:00 EDT 2026 Sauvegarde OK le Wed May 13 02:15:00 EDT 2026

Commande complete :

>> ajoute a la fin du fichier (au lieu d'ecraser). Pour la date, $(date) entoure de guillemets dans la chaine echo. Format : echo "texte $(date)" >> fichier.
echo "Sauvegarde OK le $(date)" >> /var/log/historique-sauvegardes.log

Difference avec Q1 :

Variante avec date formattee :

echo "[$(date '+%Y-%m-%d %H:%M:%S')] Sauvegarde OK" \
    >> /var/log/historique-sauvegardes.log

Question 3 / 9 2 alternatives en bash

Gerer une erreur sur une seule ligne

En programmation classique on utilise try/catch pour gerer les erreurs. En bash, on a 2 facons originales de le faire sur une seule ligne, sans bloc, qui peuvent surprendre quand on vient d'un autre langage.
Methode Forme Logique
1. Reagir a l'echeccmd || echo "erreur"Si le code de sortie est non-nul, executer la suite
2. Capturer le stderrcmd 2> erreur.txtDetourner le flux d'erreurs (stderr, fd 2) vers un fichier
a) Methode 1 : afficher "Erreur de sauvegarde" si backup-ircd.sh echoue :
b) Methode 2 : capturer les messages d'erreur de backup-ircd.sh dans /var/log/erreurs.txt :
|| est un operateur logique : il declenche la commande suivante SI la premiere echoue (code de sortie != 0). 2> est une redirection : il deroute le canal stderr (file descriptor 2) vers un fichier. Les deux sont independantes - on peut les combiner (Q4) ou en utiliser une seule.

Methode 1 - Reagir a l'echec :

backup-ircd.sh || echo "Erreur de sauvegarde"

Methode 2 - Capturer le stderr :

backup-ircd.sh 2> /var/log/erreurs.txt

Pour un programmeur habitue au try/catch :

// JS/Java
try { backup(); } catch (e) { console.log("Erreur"); }

// Bash methode 1
backup-ircd.sh || echo "Erreur"

// La methode 2 est differente : on n'essaie pas de "rattraper", on
// se contente de DETOURNER les messages d'erreur dans un fichier.

Dans la prochaine question (Q4), on combinera les deux pour avoir le meilleur des deux mondes.

Question 4 / 9 echec + stderr dans un log

Capter les erreurs et avertir si echec

Votre script lance backup-ircd.sh. Vous voulez : (1) capturer les erreurs (stderr) dans /var/log/blabla-erreur.txt, et (2) si la commande echoue au total, afficher "blabla erreur" dans le terminal.

Donnez la commande complete (une seule ligne) :

Combiner 2> (rediriger stderr vers un fichier) et || echo "..." (afficher si echec). Ordre : la redirection s'applique a la commande, le || teste le code de sortie de l'ensemble.
backup-ircd.sh 2> /var/log/blabla-erreur.txt || echo "blabla erreur"

Decomposition :

Pour garder l'historique des erreurs (append) :

backup-ircd.sh 2>> /var/log/blabla-erreur.txt || echo "blabla erreur"

Pour aussi stopper le script :

backup-ircd.sh 2> /var/log/blabla-erreur.txt || { echo "blabla erreur"; exit 1; }

Question 5 / 9 commande silencieuse + erreur

Commande silencieuse : capturer ses erreurs

La commande cp /etc/ircd-hybrid.conf /backup/ est silencieuse quand tout va bien. Si elle echoue (fichier manquant, permissions), elle affiche un message sur stderr.
a) Si cp echoue, ajouter "Echec copie" a /var/log/erreurs.log (sans effacer le precedent) :
b) En plus, capturer aussi le message d'erreur natif de cp (stderr) dans le meme fichier :
Combiner : (1) 2>> pour rediriger le stderr de la commande vers le log, et (2) || echo "..." >> pour ajouter notre propre message daté en cas d'echec.

a) Notre message seulement :

cp /etc/ircd-hybrid.conf /backup/ \
    || echo "Echec copie" >> /var/log/erreurs.log

b) Notre message + le stderr natif :

cp /etc/ircd-hybrid.conf /backup/ 2>> /var/log/erreurs.log \
    || echo "Echec copie le $(date)" >> /var/log/erreurs.log

Le 2>> capture le stderr de cp (avant le ||), et le echo apres le || n'est execute que si cp a echoue. Resultat : si cp reussit, rien dans le log ; si cp echoue, deux lignes (message natif + notre message date).

Question 6 / 9 || pour gerer un echec

Reagir quand cp echoue

Votre script de sauvegarde lance cp /var/lib/ircd-hybrid/data /var/backups/. Vous voulez (a) afficher un message d'erreur, puis (b) quitter le script.
a) Afficher "Erreur de copie" si cp echoue :
b) En plus, quitter le script avec exit 1 :
|| execute la commande suivante seulement si la premiere echoue. Pour grouper plusieurs commandes : { ... ; } avec espace et point-virgule.

a) Message simple :

cp /var/lib/ircd-hybrid/data /var/backups/ || echo "Erreur de copie"

b) Message + exit :

cp /var/lib/ircd-hybrid/data /var/backups/ || { echo "Erreur de copie"; exit 1; }

Notez les accolades avec espace, le point-virgule apres chaque commande dans le groupe, et le ; final avant }.

Question 7 / 9 2> et /dev/null

Gerer les messages d'erreur

Votre script lance backup-ircd.sh. Selon le contexte, vous voulez envoyer les erreurs a 3 endroits differents.
a) stderr dans /var/log/ircd-erreurs.log en ajout :
b) Dans un cron, jeter les erreurs au neant :
c) Fusionner stdout ET stderr dans le meme fichier :
2> = redirige stderr (ecrase). 2>> = stderr en append. 2>&1 = "envoyer 2 (stderr) au meme endroit que 1 (stdout)". /dev/null = poubelle.
# a) stderr en append dans un fichier de log
backup-ircd.sh 2>> /var/log/ircd-erreurs.log

# b) stderr jete au neant (cron silencieux)
backup-ircd.sh 2> /dev/null

# c) stdout + stderr fusionnes
backup-ircd.sh >> /var/log/ircd.log 2>&1
# Variante moderne : backup-ircd.sh &>> /var/log/ircd.log

Question 8 / 9 tester un resultat

Verifier si une commande a reussi

Vous voulez verifier si ircd-hybrid est actif et, sinon, le redemarrer. Donnez 2 versions du test.

a) Variante avec $? :

b) Variante avec if ! :

Code de sortie : 0 = reussi, autre = echec. $? contient le code de la commande precedente. --quiet evite l'affichage de "active"/"inactive".
# a) Avec $? (verbeux mais explicite)
systemctl is-active --quiet ircd-hybrid
if [ $? -ne 0 ]; then
    systemctl restart ircd-hybrid
fi

# b) Avec if ! (plus elegant)
if ! systemctl is-active --quiet ircd-hybrid; then
    systemctl restart ircd-hybrid
fi

Question 9 / 9 chainage logique

&& vs || vs ;

Pour chaque chainage, choisissez le bon comportement.
cmd1 && cmd2
cmd2 s'execute
si cmd1 reussit
cmd2 s'execute
si cmd1 echoue
cmd2 s'execute
toujours
cmd1 et cmd2
en parallele
cmd1 || cmd2
cmd2 s'execute
si cmd1 reussit
cmd2 s'execute
si cmd1 echoue
cmd2 s'execute
toujours
cmd1 OU cmd2
au choix
cmd1 ; cmd2
cmd2 s'execute
si cmd1 reussit
cmd2 s'execute
si cmd1 echoue
cmd2 s'execute
toujours
cmd2 attend
5 secondes

Pattern frequent :

mkdir -p /tmp/work && cd /tmp/work || exit 1
# creer + y aller ; sinon arret

Supplement

Aller plus loin

Non evalues a l'examen mais a connaitre dans un script pro

2 questions bonus

set -euo pipefail trap 'cleanup' EXIT

Supplement 1 set -e (non evalue)

Arreter le script au premier echec

Vous avez 20 commandes dans un script et vous voulez que le script s'arrete au premier echec, sans mettre || partout.

a) Ligne en haut du script :

b) Option pour couvrir aussi les pipelines (cmd1 | cmd2 | cmd3) :

man bash section set. Pour les pipelines, l'option commence par -o pipe...
#!/bin/bash
set -e             # arret au premier echec
set -o pipefail    # arret meme dans les pipelines
set -u             # arret si variable non definie

# ou en une ligne :
set -euo pipefail

Pourquoi pipefail : par defaut, le code de sortie d'un pipeline est celui de la derniere commande. pipefail renvoie l'erreur de la premiere qui echoue dans le pipeline.

Supplement 2 trap (non evalue)

Nettoyer meme en cas d'erreur

Votre script cree un fichier /tmp/backup-en-cours.lock. Vous voulez qu'il soit toujours efface a la fin, meme si le script plante au milieu.

Ligne trap qui execute rm -f /tmp/backup-en-cours.lock a la sortie du script :

man bash section trap. Format : trap 'commande' SIGNAL. Le signal EXIT se declenche a la fin du script peu importe la cause.
trap 'rm -f /tmp/backup-en-cours.lock' EXIT

Cles :

Bilan

Ce que vous venez de pratiquer

Supplements (non evalues) : set -euo pipefail et trap 'cleanup' EXIT

R pour recommencer.

« Retour aux mini-tests