Skip to content

$ cat ./posts/bash/bash-strict-mode.sh

-rw-r--r-- 1.8K #bash

Bash strict mode is not enough

by chris · 2 min read · /bash


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 local for every variable inside a function.

The full boilerplate is six lines. It has prevented more incidents than any monitoring dashboard I have ever built.

← cd .. fris@linux:~/blog$ man bash