Bash error reporting

Two tips:

Fail fast

You probably already know that you can force Bash scripts to exit immediately if there’s an error (that is, if any command exits with a non-zero exit code) using:

#!/usr/bin/env bash
set -e

but it’s even better to use:

set -eu -o pipefail

so that the script:

  • exits on an error (-e, equivalent to -o errexit);
  • exits on an undefined variable (-u, equivalent to -o nounset);
  • exits on an error in piped-together commands (-o pipefail)1.

You can learn more about these built-ins with:

help set

Fail noisy

Failing fast is all very well but, by default scripts fail silently offering no debug information.

You can add:

set -x

to print each command before execution but it’s easy to add simple error handling using trap:.

function print_error {
    read line file <<<$(caller)
    echo "An error occurred in line $line of file $file:" >&2
    sed "${line}q;d" "$file" >&2
}
trap print_error ERR

Here we bind the print_error function to the ERR event and print out an error message and offending line of the script (extracted using sed) to STDERR.

Note the use of a <<< here string and the caller built-in to assign the line and filename of the error.

So running the script:

#!/usr/bin/env bash
set -eu -o pipefail

function print_error {
    read line file <<<$(caller)
    echo "An error occurred in line $line of file $file:" >&2
    sed "${line}q;d" "$file" >&2
}
trap print_error ERR

false

gives:

$ ./script.sh
An error occurred in line 11 of file ./test.sh:
false

There are more sophisticated ways to handle errors in Bash scripts2 but this is a concise, simple option to have to hand.


  1. Without this pg_dump ... | gzip would not be treated as an error even if pg_dump exited with a non-zero exit code. ↩︎

  2. See the Bash infinity framework for example. ↩︎

——————

Something wrong? Suggest an improvement or add a comment (see article history)
Tagged with: bash
Filed in: tips

Previous: Using pgbadger with AWS RDS
Next: Why your Django models are fat

Copyright © 2005-2024 David Winterbottom
Content licensed under CC BY-NC-SA 4.0.