Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I get the effect and usefulness of "set -e" inside a shell function?

set -e (or a script starting with #!/bin/sh -e) is extremely useful to automatically bomb out if there is a problem. It saves me having to error check every single command that might fail.

How do I get the equivalent of this inside a function?

For example, I have the following script that exits immediately on error with an error exit status:

#!/bin/sh -e  echo "the following command could fail:" false echo "this is after the command that fails" 

The output is as expected:

the following command could fail: 

Now I'd like to wrap this into a function:

#!/bin/sh -e  my_function() {     echo "the following command could fail:"     false     echo "this is after the command that fails" }  if ! my_function; then     echo "dealing with the problem" fi  echo "run this all the time regardless of the success of my_function" 

Expected output:

the following command could fail: dealing with the problem run this all the time regardless of the success of my_function 

Actual output:

the following output could fail: this is after the command that fails run this all the time regardless of the success of my_function 

(ie. the function is ignoring set -e)

This presumably is expected behaviour. My question is: how do I get the effect and usefulness of set -e inside a shell function? I'd like to be able to set something up such that I don't have to individually error check every call, but the script will stop on encountering an error. It should unwind the stack as far as is needed until I do check the result, or exit the script itself if I haven't checked it. This is what set -e does already, except it doesn't nest.

I've found the same question asked outside Stack Overflow but no suitable answer.

like image 279
Robie Basak Avatar asked Nov 01 '10 20:11

Robie Basak


People also ask

What does set e do in shell?

Set –e is used within the Bash to stop execution instantly as a query exits while having a non-zero status. This function is also used when you need to know the error location in the running code.

How do you call a function inside a shell script?

To invoke a function, simply use the function name as a command. To pass parameters to the function, add space separated arguments like other commands. The passed parameters can be accessed inside the function using the standard positional variables i.e. $0, $1, $2, $3 etc.

What does $_ mean in shell?

$_ (dollar underscore) is another special bash parameter and used to reference the absolute file name of the shell or bash script which is being executed as specified in the argument list. This bash parameter is also used to hold the name of mail file while checking emails.

What does set +E mean?

set -e stops the execution of a script if a command or pipeline has an error - which is the opposite of the default shell behaviour, which is to ignore errors in scripts. Type help set in a terminal to see the documentation for this built-in command.


1 Answers

From documentation of set -e:

When this option is on, if a simple command fails for any of the reasons listed in Consequences of Shell Errors or returns an exit status value > 0, and is not part of the compound list following a while, until, or if keyword, and is not a part of an AND or OR list, and is not a pipeline preceded by the ! reserved word, then the shell shall immediately exit.

In your case, false is a part of a pipeline preceded by ! and a part of if. So the solution is to rewrite your code so that it isn't.

In other words, there's nothing special about functions here. Try:

set -e ! { false; echo hi; } 
like image 136
Roman Cheplyaka Avatar answered Oct 05 '22 07:10

Roman Cheplyaka