Strict Mode: set -euo pipefail
Prerequisites: Error handling in scripts
By default, Bash is forgiving: it continues after errors, treats unset variables as empty, and ignores failures in the middle of pipelines. For scripts that matter, turn on strict mode at the top:
#!/usr/bin/env bash
set -euo pipefail
-e: exit on errors
The script stops as soon as a command fails:
set -e
echo "before"
ls /no/such/folder
echo "after (never printed)"
before
ls: cannot access '/no/such/folder': No such file or directory
-u: unset variables are errors
A typo in a variable name normally expands to nothing — which can be
dangerous (rm -rf "$prefix/" with an empty $prefix...). -u stops
instead:
set -u
backup_dir="/backups"
echo "Cleaning $backup_dri"
echo "never printed"
script.sh: line 3: backup_dri: unbound variable
Use ${var:-} when a variable may legitimately be unset.
-o pipefail: pipelines fail if any part fails
grep "x" /no/such/file | sort
echo "without pipefail: $?"
set -o pipefail
grep "x" /no/such/file | sort
echo "with pipefail: $?"
grep: /no/such/file: No such file or directory
without pipefail: 0
grep: /no/such/file: No such file or directory
with pipefail: 2
Normally a pipeline's status is its last command's (sort, which
succeeded). With pipefail, a failure anywhere in the pipeline counts.
Where -e doesn't apply
set -e deliberately ignores failures in some places — commands tested by
if, while, &&, and ||:
set -e
if grep -q "x" /no/such/file 2>/dev/null; then echo "found"; fi
false || echo "handled with ||"
echo "still running"
handled with ||
still running
That's what you want for intentional checks, but it also means set -e
isn't a complete safety net: failures inside functions called from an
if, or in command substitutions assigned with local, can slip through.
Keep explicit checks (|| die "...") on critical commands.
A robust script header
# illustrative
#!/usr/bin/env bash
set -Eeuo pipefail
IFS=$'\n\t'
-EmakesERRtraps (next lesson) work inside functions.- Setting
IFSto newline and tab stops unquoted expansions from splitting on spaces — a safety net for quoting mistakes.
Common mistakes
(( count++ ))whencountis0returns status 1 (the expression's old value was 0, which is "false") and kills the script underset -e. Use(( count += 1 ))orcount=$(( count + 1 )).- Relying on
set -ein scripts that aresourced into an interactive shell — it closes your terminal on the first error.