How to trap ERR when using 'set -e' in Bash

Viewed 27904

I have a simple script :

#!/bin/bash
set -e
trap "echo BOO!" ERR 

function func(){
    ls /root/
}

func

I would like to trap ERR if my script fails (as it will here b/c I do not have the permissions to look into /root). However, when using set -e it is not trapped. Without set -e ERR is trapped.

According to the bash man page, for set -e :

... A trap on ERR, if set, is executed before the shell exits. ...

Why isn't my trap executed? From the man page it seems like it should.

4 Answers

We have these options for debugging:

  • -e Exit immediately on failure
  • -E If set, any trap on ERR is inherited by shell functions
  • -u Exit when there is an unbound variable
  • -o Give a option-name to set
    • pipefail The return values of last (rightmost) command (exit code)
  • -v Print all shell input lines as they are read
  • -x Print trace of commands

For handling the errors we can catch directory with trap

trap 'echo >&2 "Error - exited with status $? at line $LINENO' ERR

Or a better version ref :

trap 'echo >&2 "Error - exited with status $? at line $LINENO:";
         pr -tn $0 | tail -n+$((LINENO - 3)) | head -n7' ERR

Or a function:

function __error_handing__(){
    local last_status_code=$1;
    local error_line_number=$2;
    echo 1>&2 "Error - exited with status $last_status_code at line $error_line_number";
    perl -slne 'if($.+5 >= $ln && $.-4 <= $ln){ $_="$. $_"; s/$ln/">" x length($ln)/eg; s/^\D+.*?$/\e[1;31m$&\e[0m/g;  print}' -- -ln=$error_line_number $0
}

and call it this way:

trap  '__error_handing__ $? $LINENO' ERR
Related