Le WordPress d'aujourd'hui, décodé pour les développeurs

Outils & workflow

set -euo pipefail : ce que ces options changent dans un script maison

Un script bash qui continue après une erreur peut déployer une mise à jour incomplète sans que personne ne s'en aperçoive. Trois options qui changent ce comportement.

Par WordPress Développement • 18 décembre 2020 • 4 min de lecture • Aucun commentaire
set -euo pipefail : ce que ces options changent dans un script maison

set -euo pipefail : cette ligne, placée en tête d’un script bash, ne fait rien de spectaculaire à l’exécution. Elle change pourtant profondément la façon dont le script se comporte face à une erreur, en le faisant passer d’un mode silencieux et permissif à un mode qui s’arrête dès que quelque chose ne se passe pas comme prévu.

Sur un script de déploiement ou de maintenance, cette différence n’est pas cosmétique. Un script qui continue après une erreur peut très bien déployer la moitié d’une mise à jour, écraser un fichier avec un contenu vide, ou passer à l’étape suivante alors qu’une commande précédente a échoué, sans qu’aucun message n’alerte la personne qui l’a lancé.

Ce que chaque option corrige précisément

Ces trois options ne se recouvrent pas : chacune corrige un comportement par défaut de bash qui, pris isolément, peut sembler anodin, mais qui devient dangereux une fois combiné aux autres dans un script de plusieurs dizaines de lignes.

-e : arrêter le script à la première commande en échec

Par défaut, bash exécute chaque ligne d’un script indépendamment du résultat de la précédente. Si une commande cp échoue parce que le fichier source n’existe plus, le script continue malgré tout vers la ligne suivante. L’option -e change ce comportement : dès qu’une commande retourne un code de sortie différent de zéro, le script s’arrête immédiatement.

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

cp source.sql /chemin/inexistant/destination.sql
echo "Cette ligne ne s'affichera jamais si la copie a échoué"

-u : signaler une variable non définie plutôt que la traiter comme vide

Sans cette option, une variable jamais définie ou mal orthographiée se comporte comme une chaîne vide, sans avertissement. Dans un script qui construit un chemin de fichier à partir de variables, cela peut conduire à manipuler un répertoire complètement différent de celui attendu, en silence.

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

echo "Suppression dans ${DOSSIRE_TEMPORAIRE}/cache"
# Faute de frappe sur DOSSIER : le script s'arrête avec -u
# au lieu de supprimer dans "/cache" à la racine

-o pipefail : le cas le plus souvent oublié

L'essentiel à retenir : -e arrête le script à la première commande en échec ; -u signale une variable non définie au lieu de l'ignorer ; -o pipefail détecte l'échec caché dans un pipe de commandes

L’option -e seule ne suffit pas dans un pipe de commandes. Par défaut, bash considère qu’un pipe a réussi dès lors que la dernière commande de la chaîne a réussi, même si une commande précédente dans ce même pipe a échoué. C’est le comportement le plus contre-intuitif des trois, et celui qui cause le plus de faux positifs dans des scripts qui semblent pourtant correctement protégés.

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

wp db export | gzip > sauvegarde.sql.gz
# Si "wp db export" échoue mais que gzip réussit sur une entrée vide,
# le script continue : la sauvegarde est vide et personne ne le sait

Avec pipefail ajouté, le pipe entier est considéré en échec dès qu’une seule de ses commandes échoue, ce qui rend visible ce cas précis : une sauvegarde vide plutôt qu’une sauvegarde absente signalée clairement.

  • -e stoppe le script à la première commande en échec, hors cas particuliers comme les conditions.
  • -u transforme une variable non définie en erreur immédiate plutôt qu’en valeur vide silencieuse.
  • -o pipefail propage l’échec d’une commande intermédiaire dans un pipe, au lieu de ne regarder que la dernière.

Les cas où cette rigueur demande un ajustement

Cette combinaison a un coût : certaines commandes retournent volontairement un code différent de zéro dans des cas normaux, par exemple une commande de recherche qui ne trouve aucun résultat. Un script strict s’arrêterait alors à tort. La solution consiste à isoler ces cas avec une gestion explicite, plutôt que de renoncer à la rigueur pour l’ensemble du script.

if ! grep -q "erreur" journal.log; then
  echo "Aucune erreur trouvée, poursuite normale"
fi

Un script qui s’arrête bruyamment sur une erreur reste préférable à un script qui continue en silence vers une catastrophe plus discrète.

Pour aller plus loin

Ajouter cette ligne à un script déjà en production ne se fait pas sans vérification : un script ancien peut reposer, sans le savoir, sur l’un des comportements permissifs que ces options suppriment. La bonne pratique consiste à l’ajouter, puis à rejouer le script dans un environnement de test pour observer où il s’arrête désormais, avant de le redéployer en confiance sur les scripts de maintenance réels.

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Partager :

À propos de l'auteur

WordPress Développement

Développeur WordPress, passionné par Elementor, le FSE et l’automatisation par IA.

Voir tous ses articles

Dans la même veine

À lire aussi