Bash: Error handling in scripts

Author: Jacek Trociński, Last Revision: 2020.04.11, Topic area: Bash

Intro

Error handling is important in Bash scripts, without it you might not even know that something has failed and finding the source of failure in problematic scripts becomes a lot harder. Here are some ways to go about handling errors in Bash scripts.

Use set -e

Use set -e to exit a script when a command fails, this also sets the exit status of the script to that of the failed command. If you do not use set -e then the script will continue to run even when a command has failed and the exit status of the script will be that of the last command in the script. Use set +e to turn off set -e functionality within a script.

Example:

#!/usr/bin/env bash

set -e

echo "Script started."

date
sleep 2
date
sleep 2
# The command dateeeee does not exist and will fail.
# set -e will cause the script to exit with the exit status of dateeeee.
dateeeee

echo "Script ended successfully."

Custom Error Handling

If you want to do something other than simply exit upon error then you can check a command for failure and then handle it. Do not use $? to check for failure, it is unnecessary.

Example:

#!/usr/bin/env bash

set -e

echo "Script started."

date
sleep 2
date
sleep 2
# The command dateeeee does not exist and will fail.
# Avoid checking commands for failure using $?.
if ! dateeeee 2>/dev/null
then
	echo "It seems there is a problem, let me try again."
	date
fi

echo "Script ended successfully."

Handle Errors in a Pipeline

If you use pipelines in your scripts then use set -e in combination with set -o pipefail in order to exit a script if any command in a pipeline fails, otherwise the exit status of a pipeline will be the last command in the pipeline and any command that failed earlier in the pipeline will not be caught.

Example:

#!/usr/bin/env bash

set -eo pipefail

echo "Script started."

# The command dateeeee does not exist and will fail.
# set -eo pipefail will cause the script to exit with the exit status of dateeeee.
dateeeee | echo "ok"

echo "Script ended successfully."