Exit Codes & Error Handling
Exit codes, short-circuit operators (&&, ||), and the standard script safety header (set -euo pipefail).
Exit Codes and Error Handling
Reading Exit Codes
Check $? after a command
ls docs/antora.yml > /dev/null 2>&1
echo "success: $?" # 0
ls /nonexistent > /dev/null 2>&1
echo "failure: $?" # 2
Common exit codes
# 0 — success
# 1 — general error
# 2 — misuse of shell builtin (bad args)
# 126 — command not executable
# 127 — command not found
# 128+N — killed by signal N (130 = Ctrl+C, 137 = kill -9)
Short-Circuit Operators
&& — run next only if previous succeeded
grep -q 'pattern' file && echo "found"
# echo runs only if grep exits 0
|| — run next only if previous failed
grep -q 'pattern' file || echo "not found"
# echo runs only if grep exits non-zero
Combined pattern — the if/else one-liner
[[ "$reply" == "y" ]] && rm "$f" && echo "Deleted." || echo "Kept."
# If reply is y AND rm succeeds: "Deleted."
# If reply is not y OR rm fails: "Kept."
Script Safety Flags
set -e — exit on any error
#!/usr/bin/env bash
set -e
# Script stops at the first command that returns non-zero
# Without this, bash happily continues past failures
set -u — error on undefined variables
set -u
echo "$UNDEFINED_VAR" # bash: UNDEFINED_VAR: unbound variable
# Catches typos in variable names
set -o pipefail — catch errors in pipelines
set -o pipefail
# Without pipefail: pipeline exit code = last command's exit code
false | true; echo $? # 0 (true succeeded, false's failure hidden)
# With pipefail: pipeline exit code = rightmost failure
set -o pipefail
false | true; echo $? # 1 (false's failure propagates)
The standard script header
#!/usr/bin/env bash
set -euo pipefail
# -e = exit on error
# -u = error on undefined variable
# -o pipefail = propagate pipeline failures
# This is the safe default for any script