Every shell script tutorial opens with the same three flags, and every one of them leaves holes wide enough to lose a production database through.
set -euo pipefail
1. What the flags actually do
-e exits on an unchecked non-zero status, -u treats unset variables as errors, and -o pipefail makes a pipeline fail when any stage fails rather than only the last one.
What -e does not do is fire inside a command substitution used in an assignment, inside a condition, or on the left side of &&. That is where the surprises live.
2. Add an internal field separator
Word splitting on spaces is the single most common source of silent breakage. Restrict it:
IFS=$'nt'
Filenames with spaces stop splitting into fragments, and loops over command output behave the way they read.
3. Trap and clean up
A script that creates temporary state must remove it on every exit path, not just the happy one:
tmp=$(mktemp -d)
cleanup() { rm -rf "$tmp"; }
trap cleanup EXIT INT TERM
4. Quote everything, then check with shellcheck
Quoting is not a style preference. Run shellcheck in CI and treat its warnings as build failures — it catches the unquoted expansion you stopped seeing three months ago.
- Always quote parameter expansions:
"$var","${arr[@]}". - Prefer
[[ ]]over[ ]in bash. - Use
localfor every variable inside a function.
The full boilerplate is six lines. It has prevented more incidents than any monitoring dashboard I have ever built.