Skip to main content

Error Handling in Scripts

Robust scripts must anticipate failures, handle unexpected conditions gracefully, and exit safely without causing data corruption.

Exit Statuses​

Every command executed in Linux returns an exit status (or return code) between 0 and 255.

  • 0 means success.
  • Any non-zero value (1-255) means failure.

You can check the exit status of the immediately preceding command using the special variable $?.

mkdir /root/secured_dir
if [ $? -ne 0 ]; then
echo "Error: Failed to create directory. Do you have root privileges?"
exit 1
fi

Defensive Programming with set​

Bash provides built-in options to make scripts strictly handle errors. You can enable them using the set command.

set -e (Exit on Error)​

Tells Bash to exit immediately if any command returns a non-zero exit status.

#!/bin/bash
set -e

echo "Starting deployment..."
cd /var/www/html # If this fails, the script stops here
git pull # If this fails, the script stops here
echo "Deployment successful."

set -u (Unbound Variables)​

Treats unset variables as an error and exits immediately. This prevents catastrophic mistakes due to typos.

#!/bin/bash
set -u

TARGET_DIR="/tmp/backup"
# Typo in variable name!
rm -rf "$TARGET_DI/files" # Will error out instead of running 'rm -rf /files'

set -o pipefail​

By default, the exit status of a pipeline (e.g., cmd1 | cmd2) is the exit status of the last command. If cmd1 fails but cmd2 succeeds, the pipeline succeeds. set -o pipefail changes this so the pipeline fails if any command in it fails.

The "Strict Mode" Paradigm​

It is highly recommended to start all robust Bash scripts with this combination:

#!/bin/bash
set -euo pipefail

Custom Error Handlers​

You can combine conditionals with the || (OR) operator to execute an error-handling function if a command fails.

die() {
echo "CRITICAL ERROR: $1" >&2
exit 1
}

cp /important/data /backup/data || die "Failed to copy data."

Best Practices​

  • Always use set -euo pipefail for scripts that modify system state or data.
  • Check $? immediately after critical commands if you need custom fallback logic.
  • Output error messages to stderr using >&2.