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

How Bash exit codes and error handling work โ€” Shell Fundamentals โ€” Bash Scripting for Developers โ€” Script Valley โ€” Script Valley