0Pricing
DevOps Bootcamp · Leçon

Mode strict avec set -euo pipefail

Activez l’arrêt immédiat en cas d’échec et comprenez exactement quelles erreurs chaque option du mode strict intercepte ou laisse passer.

Mode strict avec set -euo pipefail est une leçon DevOps Bootcamp gratuite sur CoddyKit. Ceci est la leçon 1 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DevOps Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DevOps Bootcamp comprend 4 leçons au total.

Pourquoi Bash échoue silencieusement par défaut

Par défaut, Bash continue de s’exécuter même lorsque des commandes échouent. Cela entraîne des problèmes subtils et difficiles à diagnostiquer dans les scripts de production.

Considérez ce script qui tente de créer une sauvegarde :

  • Une faute de frappe dans un chemin fait échouer cp
  • Bash ignore l’échec et poursuit son exécution
  • Le script signale une réussite alors que les données n’ont jamais été sauvegardées

C’est le problème de l’échec silencieux. Le mode strict le résout en faisant se comporter Bash comme un langage compilé : l’exécution s’arrête immédiatement dès qu’un problème survient.

#!/usr/bin/env bash
# Without strict mode — dangerous default behavior

cp /important/data /backups/data   # fails (path doesn't exist)
echo "Backup complete"              # still prints — false confidence!
rm -rf /tmp/staging                # still runs — potentially destructive

Les trois options essentielles : set -euo pipefail

Le mode strict s’active en plaçant cette ligne près du début de chaque script :

set -euo pipefail

Cette ligne active trois protections distinctes :

  • -e — quitte immédiatement si une commande renvoie un état différent de zéro
  • -u — considère les variables non définies comme une erreur (au lieu de les remplacer par une chaîne vide)
  • -o pipefail — une chaîne de commandes échoue si n’importe quelle commande qu’elle contient échoue, et pas seulement la dernière

Ensemble, ces options forment l’en-tête défensif standard des scripts Bash sérieux. Chacune intercepte une catégorie différente de bogue.

#!/usr/bin/env bash
set -euo pipefail

echo "Strict mode is now active"
echo "Every command failure will abort the script"

Comprendre set -e (errexit)

set -e (également écrit set -o errexit) force le script à se terminer immédiatement lorsqu’une commande se termine avec un état différent de zéro.

Comportements essentiels à connaître :

  • Les commandes simples telles que false, grep pattern file (aucune correspondance) et ls /nonexistent déclenchent toutes l’arrêt
  • Le code de sortie de la dernière commande du script devient le code de sortie du script
  • Les commandes dans les conditions if sont exemptées — -e ne s’applique pas à l’expression de test
  • Les commandes suivies de || true sont également exemptées (voir les séquences suivantes)

Considérez -e comme votre première ligne de défense contre la poursuite silencieuse de l’exécution après un échec.

#!/usr/bin/env bash
set -e

echo "Before failure"
ls /this/path/does/not/exist   # exits here with code 2
echo "This line never runs"

Comprendre set -u (nounset)

set -u (également écrit set -o nounset) demande à Bash de traiter toute référence à une variable non définie comme une erreur fatale.

Sans -u, une faute de frappe telle que $FLENAME au lieu de $FILENAME est remplacée silencieusement par une chaîne vide, ce qui peut entraîner un comportement inattendu — voire dangereux (imaginez rm -rf "$TMPDIR/" lorsque $TMPDIR n’est pas défini).

Exceptions importantes :

  • ${VAR:-default} — substitution sûre d’une valeur par défaut, qui ne déclenche pas -u
  • ${VAR:+value} — expansion conditionnelle, également sûre
  • "$@" et "$*" sont exemptés lorsqu’aucun argument positionnel n’est fourni
#!/usr/bin/env bash
set -euo pipefail

# Safe: provide a default for optional vars
OUTPUT_DIR="${1:-/tmp/output}"
LOG_LEVEL="${LOG_LEVEL:-info}"

echo "Writing to: $OUTPUT_DIR"
echo "Log level: $LOG_LEVEL"

# This would abort the script:
# echo "$UNDEFINED_VAR"   # bash: UNDEFINED_VAR: unbound variable

Comprendre -o pipefail

Sans pipefail, l’état de sortie d’une chaîne de commandes dépend uniquement de la dernière commande. Les échecs précédents sont ignorés silencieusement.

Exemple sans pipefail :

  • cat /missing/file | wc -l
  • cat échoue avec le code de sortie 1, mais wc -l réussit avec le code 0
  • La chaîne de commandes renvoie 0 — réussite ! Pourtant, des données ont été perdues.

Lorsque pipefail est activé, Bash renvoie le code de sortie de la commande défaillante la plus à droite. Les échecs de la chaîne de commandes deviennent ainsi visibles et peuvent être interceptés.

Remarque : pipefail n’est pas une option sous forme de lettre ; elle doit être définie avec -o pipefail.

#!/usr/bin/env bash
set -euo pipefail

# With pipefail: this aborts if grep finds nothing (exit 1)
# grep returns 1 when no match found
ps aux | grep "[n]ginx" | awk '{print $2}'

echo "If we reach here, nginx is running"

Échecs intentionnels de commandes — utiliser || true

Il est parfois acceptable qu’une commande échoue. Avec set -e, vous devez indiquer explicitement les échecs tolérés ; sinon, le script s’interrompt.

La solution idiomatique est || true, qui ajoute une solution de repli réussissant toujours :

  • command || true — ignore complètement l’échec
  • command || echo "Warning: step failed, continuing" — consigne un avertissement et poursuit l’exécution
  • command || { echo "fatal"; exit 1; } — applique une gestion personnalisée de l’échec

Ce modèle rend votre intention explicite dans le code : une commande seule signifie « cette commande doit réussir » ; || true signifie « cette commande peut échouer, ce n’est pas grave ».

#!/usr/bin/env bash
set -euo pipefail

# Remove temp dir if it exists — OK if it doesn't
rm -rf /tmp/my_workspace || true
mkdir -p /tmp/my_workspace

# Check if a service is running — OK if not
if systemctl is-active --quiet nginx 2>/dev/null || true; then
  echo "nginx is active"
fi

# Grep that may find nothing — OK
grep 'ERROR' /var/log/app.log || true

echo "Done"

Ce que set -e n’intercepte PAS

set -e comporte des exceptions et des pièges bien connus. Les comprendre évite d’avoir une confiance injustifiée :

  • Les commandes dans les conditions if / while / until — l’expression de test est exemptée par conception
  • Les commandes précédées de ! — ! false ne déclenche pas l’arrêt
  • La dernière commande avant || — par exemple false || handle_error
  • L’état de sortie d’un sous-shell dans certains contextes — par exemple VAR=$(failing_command) dans certaines versions de Bash
  • Les valeurs de retour des fonctions — seule la dernière commande d’une fonction est prise en compte

Le mode strict ne remplace pas la vérification explicite des erreurs : c’est un filet de sécurité qui intercepte la majorité des échecs accidentels.

#!/usr/bin/env bash
set -euo pipefail

# These do NOT trigger -e:
if false; then echo "never"; fi         # -e exempt in conditions
! false                                  # negation exempts
false || echo "handled"                 # || exempts the left side

# This DOES trigger -e (no condition, no ||):
# false

echo "Script continues after exempted failures"

Sous-shells et fonctions en mode strict

Les paramètres du mode strict sont hérités par les sous-shells, mais leur comportement dans les fonctions et les substitutions de commandes comporte quelques subtilités.

Règles essentielles :

  • Les fonctions héritent de -e, -u et pipefail du shell appelant
  • Un retour différent de zéro d’une fonction provoque l’arrêt de l’appelant (lorsque -e est activé) — sauf si l’appel se trouve dans une condition ou après ||
  • Substitution de commande $() : dans les anciennes versions de Bash, une commande défaillante à l’intérieur de $() peut ne pas déclencher -e dans le processus parent ; affectez d’abord le résultat, puis utilisez-le séparément par mesure de sécurité
  • Les sous-shells explicites () héritent de toutes les options
#!/usr/bin/env bash
set -euo pipefail

setup_workspace() {
  local dir="$1"
  mkdir -p "$dir"          # fails here if permissions denied
  cd "$dir"
  echo "Ready in $(pwd)"
}

# Safe pattern: assign result then use it
TODAY=$(date +%Y-%m-%d)   # capture separately
WORKDIR="/tmp/run_${TODAY}"

setup_workspace "$WORKDIR"
echo "Workspace: $WORKDIR"

Associer le mode strict à l’interception des erreurs

Le mode strict indique à Bash quand s’arrêter. Un trap sur ERR vous permet d’exécuter un nettoyage ou des diagnostics avant la fin du script.

Le modèle courant consiste à :

  • activer le mode strict au début du script
  • définir une fonction cleanup ou on_error
  • l’enregistrer avec trap 'on_error' ERR
  • éventuellement intercepter aussi EXIT pour garantir le nettoyage, quelle que soit la réussite ou l’échec

Important : utilisez set -E (E majuscule, également appelé errtrace) afin que l’interception ERR soit également héritée par les fonctions et les sous-shells — sans cette option, les interceptions ne se déclenchent que dans le corps du shell principal.

#!/usr/bin/env bash
set -Eeuo pipefail

on_error() {
  local exit_code=$?
  local line_number=${BASH_LINENO[0]}
  echo "ERROR: command failed with code ${exit_code} at line ${line_number}" >&2
}

cleanup() {
  echo "Cleaning up temporary files..." >&2
  rm -rf /tmp/my_run_dir 2>/dev/null || true
}

trap on_error ERR
trap cleanup EXIT

mkdir -p /tmp/my_run_dir
echo "hello" > /tmp/my_run_dir/output.txt
cat /tmp/my_run_dir/output.txt
echo "Done"

Désactiver localement le mode strict

Il arrive qu’un bloc de code soit volontairement « désordonné » — par exemple pour rechercher des outils facultatifs ou exécuter des commandes héritées qui renvoient une valeur différente de zéro pour des raisons qui ne sont pas des erreurs. Vous pouvez désactiver temporairement le mode strict, puis le rétablir.

Le modèle sûr :

  • enregistrez l’état avec set +e (désactive -e), exécutez le bloc, puis réactivez-le avec set -e
  • ou utilisez un sous-shell ( set +e; ... ) afin que les options du shell parent ne soient jamais modifiées
  • réactivez toujours les options dès que le bloc risqué se termine — laisser les options désactivées est une source fréquente de bogues

Préférez la forme avec sous-shell lorsque le bloc comporte plusieurs commandes, car les options sont automatiquement rétablies à la fin.

#!/usr/bin/env bash
set -euo pipefail

# Probe for optional tools without aborting
HAS_JQ=false
(
  set +e
  command -v jq > /dev/null 2>&1
  [[ $? -eq 0 ]] && echo "jq_found"
) && HAS_JQ=true || true

if [[ "$HAS_JQ" == "true" ]]; then
  echo "jq is available — using JSON output"
else
  echo "jq not found — using plain text"
fi

Modèle complet de script en mode strict

Voici un modèle prêt pour la production qui réunit toutes les bonnes pratiques du mode strict présentées dans cette leçon :

  • set -Eeuo pipefail — les quatre options, y compris errtrace
  • IFS=$'\n\t' — séparation plus sûre des mots (évite la séparation sur les espaces)
  • interceptions ERR + EXIT pour les diagnostics et le nettoyage
  • valeurs par défaut explicites pour les paramètres facultatifs
  • readonly et local pour limiter la portée des variables

Copiez ce modèle au début de chaque script Bash non trivial pour bénéficier immédiatement d’un comportement d’arrêt rapide et d’erreurs traçables.

#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'

# ── Constants ────────────────────────────────────────────
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_NAME="$(basename "$0")"

# ── Trap handlers ────────────────────────────────────────
err_handler() {
  echo "[${SCRIPT_NAME}] ERROR on line ${BASH_LINENO[0]}: exit ${?}" >&2
}
cleanup() {
  echo "[${SCRIPT_NAME}] Exiting" >&2
}
trap err_handler ERR
trap cleanup EXIT

# ── Defaults ─────────────────────────────────────────────
ENV="${1:-production}"
MAX_RETRIES="${MAX_RETRIES:-3}"

# ── Main ─────────────────────────────────────────────────
main() {
  echo "Running in env=${ENV}, max_retries=${MAX_RETRIES}"
  echo "Script dir: ${SCRIPT_DIR}"
}

main "$@"

Vérification des connaissances : comportement de pipefail

Vérifiez votre compréhension de l’influence de pipefail sur les codes de sortie des pipelines.

Récapitulatif : mode strict avec set -euo pipefail

Dans cette leçon, vous avez appris à faire échouer rapidement et explicitement les scripts Bash en utilisant le mode strict.

Les trois options et ce qu’elles contrôlent :

  • -e (errexit) — quitte le script lorsqu’une commande renvoie un statut différent de zéro ; cette règle ne s’applique pas dans les conditions ni après ||
  • -u (nounset) — interrompt le script lorsqu’une variable non définie est référencée ; utilisez ${VAR:-default} pour les variables facultatives
  • -o pipefail — fait échouer tout le pipeline si une étape échoue, et pas uniquement la dernière

Pratiques complémentaires :

  • Ajoutez -E (errtrace) afin que les pièges ERR se propagent dans les fonctions
  • Utilisez trap sur ERR et EXIT pour obtenir des informations de diagnostic et effectuer le nettoyage
  • Utilisez || true pour tolérer volontairement les échecs
  • Désactivez temporairement cette option avec set +e dans des sous-shells pour du code ancien ou de détection

Le mode strict n’est pas une solution miracle — vous devez en connaître les exceptions — mais c’est l’habitude la plus efficace pour écrire des scripts Bash fiables et défensifs.

Questions Fréquemment Posées

La leçon « Mode strict avec set -euo pipefail » est-elle gratuite ?

Oui — le texte complet de « Mode strict avec set -euo pipefail » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DevOps Bootcamp, passe à CoddyKit PRO. Le cours DevOps Bootcamp comprend 4 leçons au total.

Qu'est-ce que j'apprendrai dans « Mode strict avec set -euo pipefail » ?

Activez l’arrêt immédiat en cas d’échec et comprenez exactement quelles erreurs chaque option du mode strict intercepte ou laisse passer. Tu pratiques DevOps Bootcamp avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.

Dois-je avoir de l'expérience pour commencer DevOps Bootcamp ?

Aucune expérience préalable n'est requise. DevOps Bootcamp sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 1 sur 4.

Combien de temps prend la leçon « Mode strict avec set -euo pipefail » ?

La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.

Peux-tu écrire et exécuter du code dans cette leçon DevOps Bootcamp ?

Oui. Chaque leçon DevOps Bootcamp inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.

Toutes les leçons de ce cours

  1. Mode strict avec set -euo pipefail
  2. Gestionnaires trap pour le nettoyage et les signaux
  3. Fichiers temporaires sûrs et répertoires de verrouillage
  4. Scripts idempotents et logique de nouvelle tentative avec temporisation
← Retour à DevOps Bootcamp