Script Valley
Bash Scripting for Developers
Shell FundamentalsLesson 1.3

How Bash exit codes and error handling work

exit codes, $? variable, set -e, set -u, set -o pipefail, trap ERR, command success vs failure convention

Exit Codes: Every Command Reports Success or Failure

Exit code decision diagram

Every command in Bash exits with a numeric code. 0 means success. Any non-zero value means failure. This is the contract that makes scripting composable.

ls /tmp
echo $?   # 0 — success

ls /nonexistent
echo $?   # 2 — failure

Making Scripts Fail Safely

By default, Bash continues executing even after errors. For production scripts, always add this at the top:

#!/usr/bin/env bash
set -euo pipefail

# -e  : exit immediately on error
# -u  : treat unset variables as errors
# -o pipefail : catch failures inside pipes

set -e alone isn't enough. Without pipefail, a command like false | echo "ok" exits 0 because only the last command's exit code counts. pipefail makes the pipe fail if any stage fails.

Cleanup with trap

#!/usr/bin/env bash
set -euo pipefail

tmpfile=$(mktemp)
trap "rm -f $tmpfile" EXIT

echo "working..." > $tmpfile
# tmpfile is deleted automatically when script exits,
# whether it succeeds or fails

trap CMD EXIT runs CMD whenever the script exits — clean or crashed. Use it to remove temp files, release locks, or send failure notifications.

Up next

Bash input and output redirection fundamentals

Sign in to track progress