While the Bash man page states that:
The ERR trap is not executed if the failed command is ... part of a command executed in a && or || list ...
I hoped that code in a subshell would be in a different context and would not be subject to the above restriction. The code below shows that even subshells are not immune from this restriction:
#!/bin/bash
main()
{
local Arg="$1"
(
set -e
echo "In main: $Arg"
trap MyTrap ERR
$(exit 1)
echo "Should not get here"
)
return 1
}
MyTrap()
{
echo "In MyTrap"
}
main 1
[[ $? -eq 0 ]] || echo "failed"
echo
main 2 || echo "failed"
The above code has the following output:
In main: 1
In MyTrap
failed
In main: 2
Should not get here
failed
My present workaround is to use file persistence to save error states in MyTrap
and then inspect return codes back in the caller. For example:
MyTrap()
{
echo "_ERROR_=$?" > $HOME/.persist
echo "In MyTrap"
}
main 1
[[ -f $HOME/.persist ]] && . $HOME/.persist || _ERROR_=0
[[ $_ERROR_ -eq 0 ]] || echo "failed"
The output of the above is now:
In main: 1
In MyTrap
failed
So, the question is: Can an approach be found to do set -e/ERR subshell trapping that is immune to &&
and ||
restrictions that is simpler than the workaround above?
Notes: This question applies to:
- Bash 4.2 and higher
- Red Hat 7, CentOS 7, and related distros (that is, not Debian, etc.)
- No third-party software should be used. Packages must be available, for example, via OS-provider packages in the [CentOS-7-x86_64-DVD-1611.iso][2] repository iso (and similarly for RHEL 7, Fedora 7, etc).