objectif
Utiliser trap pour garantir un cleanup fiable (tmp, verrous), remonter les erreurs (ERR) et réagir aux signaux (INT, TERM, HUP) sans laisser d’états sales.
code minimal
#!/usr/bin/env bash
set -Eeuo pipefail
# ressources
tmp="$(mktemp)"; lock="/tmp/myjob.lock"
cleanup() {
rm -f "$tmp" "$lock" 2>/dev/null || true
# tuer les jobs en arrière-plan du script
jobs -pr | xargs -r kill -TERM 2>/dev/null || true
}
on_err() {
local rc=$?; echo "error rc=$rc at line ${BASH_LINENO[0]}: ${BASH_COMMAND}" >&2
}
# traps
trap on_err ERR # nécessite set -E pour propager dans les fonctions
trap cleanup EXIT INT TERM HUP
# section critique (exclusivité simple)
exec 9>"$lock"; flock -n 9 || { echo "already running"; exit 1; }
# travail: si interrompu, cleanup s'exécute
echo "running... tmp=$tmp"
sleep 3
echo "done"
utilisation
# 1) trap spécifique pour réagir au SIGINT/SIGTERM (arrêt coopératif)
graceful_stop() { echo "stopping..."; }
trap graceful_stop INT TERM
# 2) protéger un pipeline: remonter l'échec d'une étape (pipefail)
set -o pipefail
curl -fsSL https://api.data.pm/health | jq -e .status >/dev/null # si jq échoue, ERR se déclenche
# 3) timeout + cleanup d'un worker en arrière-plan
start_worker() { while :; do date -u +%H:%M:%S; sleep 1; done; }
start_worker & wid=$!
( sleep 5; kill -TERM "$wid" 2>/dev/null || true ) &
wait "$wid" || true # EXIT trap s'occupera de ce qu'il reste
# 4) désactiver un trap temporairement (section sensible)
trap - ERR
# ... opérations qui ne doivent pas déclencher on_err ...
trap on_err ERR
# 5) inspecter les traps actifs (debug)
trap -p
variante(s) utile(s)
# tracer les commandes échouées uniquement (xtrace sélectif)
on_err() {
local rc=$? line=${BASH_LINENO[0]} cmd=${BASH_COMMAND}
printf 'ERR rc=%d line=%s cmd=%q\n' "$rc" "$line" "$cmd" >&2
}
set -Eeuo pipefail; trap on_err ERR
# cleanup avancé: temp dir + fermeture de FD
tmpdir="$(mktemp -d)"
cleanup() {
exec 9>&- # ferme le FD 9 si ouvert
rm -rf "$tmpdir" 2>/dev/null || true
}
trap cleanup EXIT INT TERM HUP
# relayer le signal au process enfant principal (supervision simple)
run_and_forward() {
"$@" & child=$!
forward() { kill -TERM "$child" 2>/dev/null || true; }
trap forward INT TERM
wait "$child"
}
run_and_forward "node" "server.js"
# traps dans des fonctions: assurer la propagation avec `set -E`
set -E
f() { false; } # provoque ERR
trap 'echo "ERR in function at line ${BASH_LINENO[0]}" >&2' ERR
f || true
notes
trap ... EXITs’exécute toujours en fin de script (même en cas d’erreur) → idéal pour le cleanup.trap ... ERRnécessiteset -Epour se propager dans les fonctions et sous-shells déclenchés parcommand substitution.- utilisez
pipefailpour ne pas masquer les échecs dans les pipelines. - capturez et tuez les jobs en arrière-plan (
jobs -pr | xargs kill) pour éviter les orphelins. - réagissez à
INT/TERMpour un arrêt gracieux; laissezEXITassurer le nettoyage final.