Without these options a script keeps going after a failure and can do real damage with empty variables.
By default bash ignores failures and keeps running. Three options, usually written together at the top of a script, change that:
set -e(errexit): exit when a command fails.set -u(nounset): treat expanding an unset variable as an error, which catches typos likerm -rf "$buidl_dir/".set -o pipefail: a pipeline fails if any stage fails, not just the last.
set -e has deliberate exceptions you must know. It does not trigger for commands in an if/while condition, for any command in a &&/|| list except the last, or for commands negated with !. And the status of a command substitution is lost when it is used in local x=$(cmd) or echo "$(cmd)"; declare first (local x) and assign on its own line.
Commands that legitimately return non-zero need handling: grep returns 1 for no match, diff for differences. Use || true, or test them in an if.
With -u, optional parameters need defaults: "${1:-}", "${DEBUG:-0}". Some people also set IFS=$'\n\t' so unquoted expansions only split on newlines and tabs. Strict mode is a safety net, not a substitute for checking the errors you can anticipate and printing helpful messages.
Example
cd "$(mktemp -d)"
cat > strict.sh <<'EOF'
#!/usr/bin/env bash
set -euo pipefail
name=${1:-world} # -u: optional args need defaults
echo "hello $name"
count=$(grep -c foo /dev/null || true) # grep exits 1 on no match
echo "count=$count"
if ! mkdir /proc/x 2>/dev/null; then # failures inside if are fine
echo "mkdir failed, handled"
fi
echo "$undefined_var" # -u: the script dies here
echo "never printed"
EOF
bash strict.sh; echo "exit status: $?"
# hello world / count=0 / mkdir failed, handled
# strict.sh: line 10: undefined_var: unbound variable
# exit status: 1Remember
- set -euo pipefail: stop on errors, unset variables and failed pipe stages
- -e is suspended in conditions, && / || lists and after !
- Give optional variables defaults with ${var:-}
Watch out for
local out=$(cmd)hides cmd's failure from set -e because local itself succeeds.