pditommaso
pditommaso

Reputation: 3381

Why does Bash trap not capture the exit status for an undefined variable?

I need to capture error conditions in a Bash script using a trap. For this reason I've both set -e AND set -u in my script. However I've noticed that the trap defined in the script is not getting the error status. For example:

set -e
set -u

on_exit() {
  exit_status=$?
  echo exit_status=$exit_status
  exit $exit_status
}

trap on_exit EXIT

X=$Y

The above snippet prints:

line 12: Y: unbound variable
exit_status=0

Whereas I was expecting the error status to be non-zero. After removing set -e the error status is correctly reported as 1.

What's the reason for that?

Bash version: GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15)

Upvotes: 8

Views: 1008

Answers (2)

Shakiba Moshiri
Shakiba Moshiri

Reputation: 23914

Bash does trigger ERR trap Correct behavior of EXIT and ERR traps when using set -eu , but we can handle it partially this way:

defining a handler function

function _unbound_variable_handler(){
    case $1 in
        WORDPRESS_DB_HOST | MYSQL_ROOT_PASSWORD | MC_ACCESS_KEY | MC_ACCESS_KEY )
            echo please set $1 in your .env file or export it
        ;;
        * )
            echo please set $1 first then run the script.
        ;;
    esac

    exit $?;
}

set the handler for any variable you want to take care of

echo WORDPRESS_DB_HOST ${WORDPRESS_DB_HOST:?"$(_unbound_variable_handler WORDPRESS_DB_HOST)"}

sample

# bash strict mode
set -Eeuo pipefail
# debug mode
# set -x

function _unbound_variable_handler(){
    case $1 in
        WORDPRESS_DB_HOST | MYSQL_ROOT_PASSWORD | MC_ACCESS_KEY | MC_ACCESS_KEY )
            echo please set $1 in your .env file or export it
        ;;
        * )
            echo please set $1 first then run the script.
        ;;
    esac

    exit $?;
}

echo WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:?"$(_unbound_variable_handler WORDPRESS_DB_HOST)"}

output

ub.sh: line 20: WORDPRESS_DB_HOST: please set WORDPRESS_DB_HOST in your .env file or export it


NOTE

This syntax is for exiting immediately with the message you set ${varname:?"message"} and I used a function instead of a message

sample

echo WORDPRESS_DB_HOST: ${WORDPRESS_DB_HOST:-"Error on line $LINENO - WORDPRESS_DB_HOST has not been set"}

output

WORDPRESS_DB_HOST: Error on line 22 - WORDPRESS_DB_HOST has not been set

and this syntax is for setting a value to the varname ${varname:-"message"}


bash --version
GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

Upvotes: 0

chepner
chepner

Reputation: 532303

From the change log between 4.0 and 4.1:

x. Fixed a bug that caused $? to not be set correctly when referencing an unset variable with set -u and set -e enabled.

Upvotes: 7

Related Questions