I am calling a bash script (say child.sh
) within my bash script (say parent.sh
), and I would like have the errors in the script (child.sh
) trapped in my parent script (parent.sh
).
I read through the medium article and the stack exchange post. Based on that I thought I should do set -E
on my parent script so that the TRAPS are inherited by sub shell. Accordingly my code is as follows
parent.sh
#!/bin/bash
set -E
error() {
echo -e "$0: \e[0;33mERROR: The Zero Touch Provisioning script failed while running the command $BASH_COMMAND at line $BASH_LINENO.\e[0m" >&2
exit 1
}
trap error ERR
./child.sh
child.sh
#!/bin/bash
ls -al > /dev/null
cd non_exisiting_dir #To simulate error
echo "$0: I am still continuing after error"
Output
./child.sh: line 5: cd: non_exisiting_dir: No such file or directory
./child.sh: I am still continuing after error
Can you please let me know what am missing so that I can inherit the TRAPs defined in the parent script.
./child.sh
does not run in a "subshell".A subshell is not a child process of your shell which happens to be a shell, too, but a special environment where the commands from inside
(...)
,$(...)
or...|...
are run in, which is usually implemented by forking the current shell without executing another shell.If you want to run
child.sh
in a subshell, then source that script from a subshell you can create with(...)
:which will inherit your
ERR
trap because ofset -E
.Notes:
There are other places where bash runs the commands in a subshell: process substitutions (
<(...)
), coprocesses, thecommand_not_found_handle
function, etc.In some shells (but not in bash) the leftmost command from a pipeline is not run in a subshell. For instance
ksh -c ':|a=2; echo $a'
will print 2. Also, not all shells implement subshells by forking a separate process.Even if bash infamously allows functions to be exported to other bash scripts via the environment (with
export -f funcname
), that's AFAIK not possible with traps ;-)