Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is bash errexit not behaving as expected in function calls?

Tags:

bash

In the bash man page, it states:

Exit immediately if a pipeline (which may consist of a single simple command),
a subshell command enclosed in parentheses, or one of the commands executed as part of a command list enclosed by braces...

So I assumed that a function should be considered a command list enclosed by braces. However, if you apply a conditional to the function call, errexit no longer persists inside the function body and it executes the entire command list before returning. Even if you explicitly create a subshell inside the function with errexit enabled for that subshell, all commands in the command list are executed. Here is a simple example that demonstrates the issue:

function a() { b ; c ; d ; e ; }
function ap() { { b ; c ; d ; e ; } ; }
function as() { ( set -e ; b ; c ; d ; e ) ; }
function b() { false ; }
function c() { false ; }
function d() { false ; }
function e() { false ; }

( set -Eex ; a )
+ a
+ b
+ false

( set -Eex ; ap )
+ ap
+ b
+ false

( set -Eex ; as )
+ as
+ set -e
+ b
+ false

Now if I apply a conditional to each of them...

( set -Eex ; a || false )
+ a
+ b
+ false
+ c
+ false
+ d
+ false
+ e
+ false
+ false

( set -Eex ; ap || false )
+ ap
+ b
+ false
+ c
+ false
+ d
+ false
+ e
+ false
+ false

( set -Eex ; as )
+ as
+ set -e
+ b
+ false
+ c
+ false
+ d
+ false
+ e
+ false
+ false
like image 752
Craig Avatar asked Nov 05 '13 12:11

Craig


People also ask

What is the purpose of set E?

set -e causes a script immediately exits when it encounters an error. If one of the commands (or executables) that the script calls, returns a non-zero value, this is considered an error.

What does set e do zsh?

set -e causes the shell to exit if any subcommand or pipeline returns a non-zero status.

What is Errexit?

errexit converts, formats, and prints its args under control of the format. The format and args are identical to the format and args described by printf(3P). It then invokes the exit(2P) routine with a status of status.

What is Pipefail in bash?

pipefail. If set, the return value of a pipeline is the value of the last (rightmost) command to exit with a non-zero status, or zero if all commands in the pipeline exit successfully. This option is disabled by default.


1 Answers

You started to quote the manual but then you cut the bit that explained this behaviour, which was in the very next sentence:

-e Exit immediately if a pipeline, which may consist of a single simple command, a subshell command enclosed in parentheses, or one of the commands executed as part of a command list enclosed by braces returns a non-zero status. The shell does not exit if the command that fails is part of the command list immediately following a while or until keyword, part of the test in an if statement, part of any command executed in a && or || list except the command following the final && or ||, any command in a pipeline but the last, or if the command’s return status is being inverted with !.

like image 133
Gareth Rees Avatar answered Nov 15 '22 23:11

Gareth Rees