Document

SUBSCRIBE TO GET FULL ACCESS TO THE E-BOOKS FOR FREE 🎁SUBSCRIBE NOW

Professional Dropdown with Icon

SUBSCRIBE NOW TO GET FREE ACCESS TO EBOOKS

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), trap de nettoyage, fonctions avec local, tableaux indexés et associatifs, la distinction "$@" vs $*, et un aperçu getopts — 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 / -u cassent 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

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.