Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using command substitution or similar, but still having script exit (using set -e)

Tags:

bash

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))

like image 976
coiax Avatar asked Sep 27 '13 15:09

coiax


People also ask

Which symbol is used with the SET command for command substitution?

For explanation I would say: set statement can also be used for command substitution. There can be a problem especially when the output of the command begins with a-. It may happen that set interprets it as an option. To avoid this condition, we have to use — (double hyphen) immediately after set.

How do you exit a script command?

One of the many known methods to exit a bash script while writing is the simple shortcut key, i.e., “Ctrl+X”. While at run time, you can exit the code using “Ctrl+Z”.

How do you exit a script if command fails?

Exit When Any Command Fails This can actually be done with a single line using the set builtin command with the -e option. Putting this at the top of a bash script will cause the script to exit if any commands return a non-zero exit code.

What is command substitution give an example?

An example with date : The command substitution syntax is $() . The command itself is date . Combining both we get $(date) , its value is the result of the substitution (that we could get after execution). We save that value in a variable, $thedate , for later use.


1 Answers

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

like image 84
rici Avatar answered Dec 10 '22 19:12

rici