Trap bash errors from child script

810 views Asked by At

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.

1

There are 1 answers

0
AudioBubble On

./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 (...):

(. ./child.sh)

which will inherit your ERR trap because of set -E.

Notes:

There are other places where bash runs the commands in a subshell: process substitutions (<(...)), coprocesses, the command_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 ;-)