Reputation: 640
Bash doesn't seem to pass the "exit on error" environment flag into command substitution shells.
I am using a large number of command substitutions (to get around bash's lack of return values), but I'd still like the whole script to go down if something in the subshell fails.
So, for example:
set -e
function do_internet {
curl not.valid.address
}
answer=$(do_internet)
I'd like the script to stop there and then, and not continue. (I hoped that setting -e would stop from having to put '|| die' on everything.
Am I doing something wrong; and/or is there any way around this?
Here's a little example:
#!/bin/bash
set -e
echo "You should only see this line, and not any other line."
function foo {
false
echo "The above line is false. Figure that one out, Plato."
}
bar=$(foo)
echo $bar
It prints both lines.
(Using GNU bash, version 4.2.25(1)-release (x86_64-pc-linux-gnu)
)
Upvotes: 5
Views: 1090
Reputation: 241841
There is a difference in handling of -e
between subshells created with (...)
, as in Why doesn't bash flag -e exit when a subshell fails?, and subshells created with command substitution $(...)
, as in the OP.
According to the section COMMAND EXECUTION ENVIRONMENT
in the bash manual (and slightly confusingly):
Subshells spawned to execute command substitutions inherit the value of the -e option from the parent shell. When not in posix mode, bash clears the -e option in such subshells.
Regardless of the posix setting, the -e
only applies to the subshell created for the purposes of command substitution. So:
$ set -e
# The subshell has -e cleared
$ echo $(false; echo foo)
foo
$ set -o posix
# Now the subshell has -e, so it terminates at `false`
$ echo $(false; echo foo)
$
Nonetheless, -e
does apply to the execution of a command which only sets a variable. So
set -e
a=$(false)
will terminate the shell.
However, -e
does not apply to individual commands in a function. In the case of
fail() {
false
echo "failed"
}
The return value of fail
is 0 (i.e. success) because the echo
(which was the last command executed) succeeded. Consequently
a=$(fail) && echo ok
will set a
to failed
and then print ok
Upvotes: 7