exit shell script from a subshell
You could decide that the exit status 77 for instance means exit any level of subshell, and do
set -E
trap '[ "$?" -ne 77 ] || exit 77' ERR
(
echo here
(
echo there
(
exit 12 # not 77, exit only this subshell
)
echo ici
exit 77 # exit all subshells
)
echo not here
)
echo not here either
set -E
in combination with ERR
traps is a bit like an improved version of set -e
in that it allows you to define your own error handling.
In zsh, ERR traps are inherited automatically, so you don't need set -E
, you can also define traps as TRAPERR()
functions, and modify them through $functions[TRAPERR]
, like functions[TRAPERR]="echo was here; $functions[TRAPERR]"
You could kill the original shell (kill $$
) before calling exit
, and that'd probably work. But:
- it seems rather ugly to me
- it will break if you have a second subshell in there, i.e., use a subshell inside a subshell.
Instead, you could use one of the several ways to pass back a value in the Bash FAQ. Most of them aren't so great, unfortunately. You may just be stuck checking for errors after each function call (-e
has a lot of problems). Either that, or switch to Perl.
As an alternative to kill $$
, you may also try kill 0
, it will work in the case of nested subshells (all callers and side process will receive the signal) … but it's still brutal and ugly.