Script foundations

Return a useful exit status

Use zero for success, non-zero for failure, and preserve the command result automation needs.

10 minute lesson

~~~

Every command finishes with an exit status, a number from 0 to 255. Status zero means success; other values identify a failed or exceptional outcome. Shell automation composes commands through exit status: if, &&, ||, cron, systemd, and CI pipelines all read it. Your script reports one too, whether you thought about it or not.

Read a status

The special parameter $? holds the status of the last command:

ls /etc/hostname
# /etc/hostname
printf '%s\n' "$?"
# 0

ls /nonexistent
# ls: cannot access '/nonexistent': No such file or directory
printf '%s\n' "$?"
# 2

Observe the status with printf '%s\n' "$?" immediately afterward. Any command you run in between — even an innocent echo — replaces it with its own status.

Fail early and clearly

A script should stop with a non-zero status the moment its requirements aren’t met. Check a required command:

if ! command -v curl >/dev/null 2>&1; then
  printf '%s\n' 'curl is required' >&2
  exit 1
fi

command -v curl succeeds when curl exists on PATH and fails otherwise. We discard its output because only the status matters here. exit 1 makes the failure visible to whatever ran the script.

To verify both paths, run the script normally and with a restricted PATH:

PATH=/nonexistent bash check-tools.sh
# curl is required
printf '%s\n' "$?"
# 1

The trap: exiting zero by accident

Without an explicit exit, a script returns the status of its last command. That rule causes a classic bug:

if ! tar -czf /mnt/backups/site.tar.gz -C /var/www .; then
  printf '%s\n' 'backup failed' >&2
fi
# script ends here — printf succeeded, so the script exits 0

The error message went out, but printf was the last command and it succeeded, so the script reports success. Cron marks the job green and nobody looks again for months.

Do not print an error and then accidentally exit zero. Callers trust the status more than human prose — put exit 1 right after the message, every time.

Lesson completed

Take this course offline

Get every free book and course as PDF and EPUB files.

Get the download library →