ERR trap is not to run code when the shell itself exits with a non-zero error code, but when any command run by that shell that is not part of a condition (like in
if cmd..., or
cmd || ......) exits with a non-zero exit status (the same conditions as what causes
set -e to exit the shell).
If you want to run code upon exit of the shell with non-zero exit status, you should add a trap on
EXIT instead and check
trap '[ "$?" -eq 0 ] || echo hi' EXIT
Note however that upon a trapped signal, both the signal trap and the EXIT trap would be run, so you may want to do it like:
trap killed_by=INT INT
trap killed_by=TERM TERM
if [ -n "$killed_by" ]; then
echo >&2 "Ouch! Killed by $killed_by"
elif [ "$ret" -ne 0 ]; then
echo >&2 "Died with error code $ret"
Or to use exit status like
$((signum + 128)) upon signals:
for sig in INT TERM HUP; do
trap "exit $((128 + $(kill -l "$sig")))" "$sig"
[ "$ret" -eq 0 ] || echo >&2 "Bye: $ret"' EXIT
If you want the
ERR trap to fire, just run a command with a non-zero exit status like