Rendre un script robuste

Le mode strict de Bash, trap pour nettoyer, mktemp, les erreurs sur la sortie d'erreur avec un code de retour, l'idempotence et shellcheck : savoir où s'arrête un script et ce qu'il laisse derrière lui.

  • 30 cartes
  • 5 thèmes
  • Gratuit

Le programme, thème par thème

Le poids de chaque thème suit celui que lui donne l'examen.

  1. Notions
  2. Questions
  3. Ranger et relier
  4. Mises en situation
  5. Comprendre

Quelques cartes du deck

  • Mode strict : de quoi s'agit-il ?

    Voir la réponse

    Trois réglages de Bash qui font échouer un script au lieu de le laisser continuer : set -e (arrêt sur erreur), set -u (variable non définie) et set -o pipefail (échec dans un tube).

    Sans lui, cd /nope échoue et le script poursuit avec rm -rf * dans le mauvais dossier. Mais set -e ignore les échecs d'un test (if, &&, ||) : il ne remplace pas la vérification des cas prévisibles.

  • Que se passe-t-il à l'exécution de ce script ?

    ```bash
    set -e
    cd /nope
    echo fini
    `

    • Il s'arrête sur l'erreur de cd, code 1, sans afficher fini
    • Il affiche l'erreur de cd, puis fini, et rend le code 0
    • Il affiche fini sans erreur, car cd ne fait que changer de dossier
    • Il demande une confirmation avant de poursuivre le script
    Voir la réponse

    Il s'arrête sur l'erreur de cd, code 1, sans afficher fini

    cd /nope échoue (« No such file or directory ») ; sous set -e, tout échec de commande simple arrête le script avec le code de cette commande, ici 1. Sans set -e, fini s'afficherait.

  • Avec set -u, lire une variable jamais définie arrête le script sur le message « unbound variable » ; sans lui, Bash la remplace par ….

    Voir la réponse

    Avec set -u, lire une variable jamais définie arrête le script sur le message « unbound variable » ; sans lui, Bash la remplace par une chaîne vide.

    C'est ce qui attrape la faute de frappe rm -rf "$dosier"/* : sans -u, la variable vide donne /*. Pour une variable facultative, une valeur par défaut évite l'arrêt : ${1:-defaut}.

  • pipefail : de quoi s'agit-il ?

    Voir la réponse

    Réglage qui donne à un tube le code de la dernière commande qui a échoué, au lieu de celui de sa seule dernière commande.

    false | true rend 0 par défaut : l'échec de false passe inaperçu. Avec set -o pipefail, il rend 1, et set -e peut alors arrêter le script.

  • Chaque nuit, le dossier /tmp grossit de 2 Go jusqu'à remplir le disque. Le script de traitement crée un fichier avec tmp=$(mktemp) et le supprime à sa dernière ligne, mais s'arrête parfois sur une erreur. Quelle correction est juste ?

    • Ajouter trap 'rm -f "$tmp"' EXIT juste après mktemp
    • Écrire le rm -f au début du script plutôt qu'à la fin
    • Remplacer mktemp par un nom fixe dans /tmp
    • Ajouter set -u pour que le script s'arrête plus tôt
    Voir la réponse

    Ajouter trap 'rm -f "$tmp"' EXIT juste après mktemp

    Quand le script s'arrête avant sa dernière ligne, le rm final n'est jamais lancé et le fichier reste. Le trap EXIT s'exécute quelle que soit la façon dont le script se termine. Un rm au début supprimerait un fichier qui n'existe pas encore.