-
-
Save eentzel/3937aa88f8e263ace3d2 to your computer and use it in GitHub Desktop.
$ cat test.sh | |
#!/usr/bin/env bash | |
set -e | |
foo () { | |
echo $(echo "subshell foo"; exit 11) | |
} | |
bar () { | |
result=$(echo "subshell bar"; exit 22) | |
echo $result | |
} | |
indirection () { | |
var=$(bar) | |
echo "indirect", $var | |
} | |
foo | |
indirection | |
bar | |
$ ./test.sh | |
subshell foo | |
indirect, subshell bar | |
$ echo $? | |
22 | |
$ |
The issue seems to be with command substitutions specifically, and variable assignments having odd semantics around them.
-e Exit immediately if a command exits with a non-zero status.
$(...)
is a command substitution, not a command. The actual command in foo
is echo $(...)
, which exist with status 0. bar
's command is a variable set without a command name:
If there is a command name left after expansion, execution proceeds as described below. Otherwise, the command exits. If one of the expansions contained a command substitution, the exit status of the command is the exit status of the last command substitution performed. If there were no command substitutions, the command exits with a status of zero.
It also looks like -e
doesn't correctly propagate in bash, but does in dash. dash otherwise has the same semantics regarding the substitution.
$ bash
bash$ (set -e; echo $(echo foo; false; echo bar)))
foo bar
bash$ exit
$ sh
dash$ (set -e; echo $(echo foo; false; echo bar)))
foo
Well, at least this explains a lot of the similar issues I had in the past.
Also looks like github's having issues updating comments, the one with the link didn't show for me until I added my (now rather redundant) comment...
Today I Learned that
set -e
doesn't apply to a to a subshell unless you assign the result to a variable...