Bash avancé : fonctions, arrays et set -euo pipefail
À la fin de ce tutoriel bash avancé, vous saurez écrire des scripts robustes :
set -euo pipefail(et ses pièges),trapde nettoyage, fonctions aveclocal, tableaux indexés et associatifs, la distinction"$@"vs$*, et un aperçugetopts— labs dans/tmp, sans secrets. Ce n’est pas un redo de bash scripting (shebang, if/for débutant, hello world).Niveau : Intermédiaire · Temps estimé : 45–55 min · Versions testées : Ubuntu 22.04 / 24.04, Debian 12 ; notes Rocky/Alma 9 · Dernière vérification : 2026-09-11
Slug proposé :
linux-bash-avance· Série : Linux Shell & Automation · Remplace / fusionne : N/A — création (chapitre 1)
Prérequis
- Hub Linux Shell & Automation
- P5 bash scripting terminé : variables,
if/for, exit codes, fonctions basiques — on approfondit, on ne recommence pas - bash ≥ 4 (associatifs) : Ubuntu/Debian/Rocky OK ;
bash --version - Éditeur +
/tmp/lab-bash-avance; aucun mot de passe / token dans les scripts
Coût : 0 €. Tout le lab est jetable sous /tmp.
Ce que nous allons construire
set -euo pipefail (+ pièges -u / pipefail)
→ trap EXIT/ERR/INT · nettoyage
→ Fonctions · local · return
→ Arrays indexés + associatifs
→ "$@" vs $* · getopts bref
→ Mini CLI lab + nettoyage
(Schéma à remplacer par une image locale Excalidraw / draw.io, alt : « Bash avancé : set -euo pipefail, trap, fonctions local, arrays, getopts ».)
Premier chapitre de Linux Shell & Automation. Basics pose le socle ; ici on vise des scripts ops qui échouent tôt, nettoient, et acceptent des options sans spaghetti. En CI comme sur un VPS, un script sans pipefail peut masquer un grep/curl en échec et « réussir » le job — d’où l’insistance sur l’en-tête défensif.
Étape 1 — set -euo pipefail : robustesse et pièges
| Option | Effet | Piège fréquent |
|---|---|---|
-e |
Exit si commande échoue | Ignore dans if cmd; then / cmd || true |
-u |
Exit si variable non définie | ${1} sans défaut ; boucles sur tableaux vides mal quotés |
-o pipefail |
Le pipeline échoue si un étage échoue | Sans pipefail, seul le statut de la dernière commande compte |
mkdir -p /tmp/lab-bash-avance && cd /tmp/lab-bash-avance
# Démo pipefail : sans lui, le faux succès trompe
bash -c 'set -e; false | true; echo "sans pipefail on arrive ici"'
bash -c 'set -eo pipefail; false | true; echo "jamais"' || echo "avec pipefail : échec attendu OK"
# Démo -u
bash -c 'set -u; echo "$UNSET_VAR"' 2>/dev/null || echo "unbound variable — OK"
# Défaut sûr :
bash -c 'set -u; echo "${UNSET_VAR:-fallback}"'
Squelette d’en-tête recommandé (ops) :
cat > /tmp/lab-bash-avance/skel.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
# … corps …
EOF
chmod +x /tmp/lab-bash-avance/skel.sh
Pas un hello world : le shebang est déjà acquis en P5. L’enjeu = quand
-e/-ucassent un script « qui marchait ».
Étape 2 — trap : nettoyer même en cas d’échec
trap accroche des commandes aux signaux / événements (EXIT, ERR, INT).
cat > /tmp/lab-bash-avance/trap-lab.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
WORKDIR=$(mktemp -d /tmp/lab-bash-avance/work.XXXXXX)
cleanup() {
local ec=$?
rm -rf "$WORKDIR"
echo "cleanup (exit=$ec)" >&2
}
trap cleanup EXIT
trap 'echo "INT — interruption" >&2; exit 130' INT
echo "work=$WORKDIR" > "$WORKDIR/note.txt"
cat "$WORKDIR/note.txt"
# Simuler une erreur après création :
false
EOF
chmod +x /tmp/lab-bash-avance/trap-lab.sh
bash /tmp/lab-bash-avance/trap-lab.sh || true
ls /tmp/lab-bash-avance/work.* 2>/dev/null || echo "WORKDIR effacé par trap — OK"
| Signal / event | Usage lab |
|---|---|
EXIT |
Toujours nettoyer fichiers temp |
ERR |
Loguer le numéro de ligne (trap '… $LINENO' ERR) |
INT |
Ctrl+C propre |
Étape 3 — Fonctions, local, et portée
Les fonctions P5 suffisent pour factoriser ; en avancé : local, codes de retour, arguments nommés via $@.
cat > /tmp/lab-bash-avance/funcs.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
log() {
local level=$1
shift
printf '[%s] %sn' "$level" "$*" >&2
}
require_file() {
local f=$1
[[ -f "$f" ]] || { log ERROR "manque $f"; return 1; }
}
sum_two() {
local a=$1 b=$2
echo $((a + b))
}
require_file /etc/os-release
log INFO "somme=$(sum_two 3 4)"
# variable locale invisible dehors :
f() { local secret=42; }
f
# echo "${secret:-unset}" → unset (attendu)
EOF
bash /tmp/lab-bash-avance/funcs.sh
| Pratique | Pourquoi |
|---|---|
local |
Évite de polluer l’environnement global |
return vs exit |
return sort de la fonction ; exit tue le script |
shift après $1 |
Traite le reste comme message / liste |
Étape 4 — Arrays indexés et associatifs
cat > /tmp/lab-bash-avance/arrays.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
# Indexé
hosts=(app01 app02 db01)
hosts+=("cache01")
echo "count=${#hosts[@]}"
echo "first=${hosts[0]}"
echo "all=${hosts[*]}"
for h in "${hosts[@]}"; do
echo "host=$h"
done
# Associatif (bash 4+)
declare -A ports=( [app]=8080 [db]=5432 [cache]=6379 )
ports[web]=443
echo "db port=${ports[db]}"
for k in "${!ports[@]}"; do
echo "$k -> ${ports[$k]}"
done
EOF
bash /tmp/lab-bash-avance/arrays.sh
| Syntaxe | Sens |
|---|---|
"${arr[@]}" |
Éléments séparés (sûr dans for) |
"${arr[*]}" |
Jointure (souvent un seul mot selon IFS) |
"${!assoc[@]}" |
Clés d’un associatif |
${#arr[@]} |
Nombre d’éléments |
Avec set -u, itérer "${arr[@]}" sur un tableau vide est OK ; ${arr[0]} sur vide peut échouer — testez ${arr[0]-} ou ${#arr[@]}. Pour passer un array à une fonction : fn "${arr[@]}" puis, dans fn, local args=("$@") — jamais fn $arr.
Étape 5 — "$@" vs $* et getopts bref
cat > /tmp/lab-bash-avance/args.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
demo_at() {
printf 'AT:';
printf ' <%s>' "$@"
printf 'n'
}
demo_star() {
printf 'STAR:'
printf ' <%s>' "$*"
printf 'n'
}
demo_at "a b" "c"
demo_star "a b" "c"
EOF
bash /tmp/lab-bash-avance/args.sh a unused
| Forme | Comportement |
|---|---|
"$@" |
Chaque argument reste un mot (préféré) |
"$*" |
Un seul mot (joint par IFS) |
$* / $@ sans guillemets |
Cassent les espaces — à éviter |
getopts (options courtes) — aperçu ops, pas un cours getopt long :
cat > /tmp/lab-bash-avance/cli.sh << 'EOF'
#!/usr/bin/env bash
set -euo pipefail
verbose=0
outfile=""
usage() { echo "Usage: $0 [-v] [-o fichier] args…" >&2; exit 2; }
while getopts ":vo:" opt; do
case "$opt" in
v) verbose=1 ;;
o) outfile=$OPTARG ;;
*) usage ;;
esac
done
shift $((OPTIND - 1))
(( verbose )) && echo "verbose on" >&2
echo "outfile=${outfile:-"(stdout)"} remaining=$*"
# Toujours "$@" pour déléguer :
printf 'remaining items:'; printf ' <%s>' "$@"; echo
EOF
chmod +x /tmp/lab-bash-avance/cli.sh
/tmp/lab-bash-avance/cli.sh -v -o /tmp/lab-bash-avance/out.txt "foo bar" baz
Étape 6 — Vérification et nettoyage
# Checklist rapide
bash -n /tmp/lab-bash-avance/funcs.sh # parse only
bash -n /tmp/lab-bash-avance/cli.sh
command -v shellcheck >/dev/null && shellcheck /tmp/lab-bash-avance/*.sh ||
echo "shellcheck optionnel : sudo apt install shellcheck"
rm -rf /tmp/lab-bash-avance
echo "lab bash avancé nettoyé — OK"
Validé si : vous expliquez -e/-u/pipefail, un trap EXIT efface un temp, une fonction utilise local, un associatif liste clés/valeurs, "$@" préserve les espaces, getopts lit -v/-o. Emportez le squelette set -euo pipefail + trap cleanup EXIT dans vos prochains scripts de la série (grep/awk/timers).
Erreurs fréquentes
| Symptôme | Cause | Correction |
|---|---|---|
unbound variable |
set -u + var absente |
${var:-défaut} ou tester [[ -v var ]] |
| Pipeline « vert » alors qu’une étape fail | Pas de pipefail |
set -o pipefail |
trap ne nettoie pas |
Erreur avant le trap |
Placer trap tôt après set |
| Fuite de variables | Oubli de local |
local dans chaque fonction |
for x in $list casse les espaces |
Pas de tableau / pas "$@" |
Arrays + "${arr[@]}" |
| Associatif refuse | bash 3 (macOS old) | bash ≥ 4 ; declare -A |
getopts ignore les longs --help |
getopts = options courtes | Documenter ; ou parser manuel / getopt |
Quiz (3 questions)
1. Que change set -o pipefail ?
– A. Désactive les pipes
– B. Fait échouer le pipeline si n’importe quel étage échoue
– C. Force -u
2. Pourquoi "$@" plutôt que $* pour déléguer des arguments ?
– A. C’est plus court
– B. "$@" préserve chaque argument (y compris avec espaces)
– C. $* est interdit par bash
3. Rôle principal de local dans une fonction ?
– A. Rendre le script plus lent
– B. Limiter la portée de la variable à la fonction
– C. Remplacer trap
Réponses : 1‑B · 2‑B · 3‑B
FAQ
set -e suffit-il en prod ?
Non seul : ajoutez pipefail, des défauts pour -u, des trap de cleanup, et testez les branches if. Beaucoup de scripts « ops » cassent sur un grep sans match (exit 1) — gérez explicitement (grep … || true ou if grep …). Même logique pour curl -f : l’échec HTTP devient un statut non zéro, ce qui est souvent désirable sous -e.
Arrays vs arguments positionnels ?
$1… pour CLI courte ; arrays dès qu’une liste grandit ou doit être passée entre fonctions. Associatifs = petites maps (ports, régions).
Faut-il ShellCheck ?
Fortement recommandé (shellcheck script.sh) : attrape les guillemets et $@ oubliés. Hors obligation de ce lab.
Pour aller plus loin
man bash(sections PARAMETERS, Arrays),help getopts, ShellCheck wiki- Suite : grep et ripgrep
- Prérequis P5 : bash scripting · hub Shell & Automation
Maillage série Linux Shell & Automation
| ← Précédent | Hub Linux Shell & Automation |
| → Suivant | grep et ripgrep : chercher code et logs |
| Prérequis P5 | Bash scripting |
| Hub | Linux Shell & Automation |
Meta publication (à remplir dans Rank Math / SEO)
- Title SEO : Bash avancé : fonctions, arrays, set -euo (2026)
- Meta description (≤ 155) : Écrivez des scripts bash robustes : set -euo, fonctions, arrays. Suite bash Basics — DevOps 2026.
- Focus keyphrase : bash avancé
- KW secondaires : set -euo pipefail, bash arrays, getopts, trap bash
- Schemas Rank Math : Article + HowTo (étapes lab) + FAQ (3 questions ci-dessus)
- Image mise en avant :
assets/web/devopelastichayway/cover-linux-bash-avance-1200x630.webp(Visuels Linux — WebP 1200×630) - Catégorie : Linux · Niveau : Intermédiaire
- Slug :
linux-bash-avance - Statut : HOLD — draft only (ne pas publier)
← Retour parcours Linux — Basics, Admin, Réseau & Sécurité, Shell & Automation.