Executing a bash function with set -e without exiting the shell

Consider the following function

function current_dir { set -e git foobar echo "I will not print this, because git foobar returned a non-zero exit code" } 

Now, when I send the function and try to call it in my shell, it will exit not only from the function, but also from the shell itself.

How can this be avoided?

+6
source share
3 answers

If you do not need a function to execute in the current shell (for example, it does not set the parameter values ​​that should be visible to the caller), you can make the body of the function a subshell, and not a group of commands:

 current_dir () ( set -e git foobar echo "I will not print this, because git foobar returned a non-zero exit code" ) 
+5
source

As far as I know, set -e will do exactly what you see: exit the shell completely as soon as the command exits with a non-zero status.

You can try reformulating your function with trap or with && between the commands:

 function current_dir { git foobar && echo "I will not print this, because git foobar returned a non-zero exit code" } 

or (more readability):

 function current_dir { trap 'trap - ERR; return' ERR git foobar ...other commands... echo "I will not print this, because a command returned a non-zero exit code" } 

If you really need set -e for some reason, you can temporarily disable it with set +e and re-enable it after your critical section.

+4
source

"set -e" is used to exit immediately when a command (pipeline or subcommand command, etc.) exits with non-zero status.

By default, BASH ignores errors and continues to interpret your script. This can cause a very bad surprise, for example:

  if ! lss myLock then touch myLock; echo "No lock, I can do the job"; rm -f myLock fi 

The result of this script is:

 bash: lss : commande introuvable No lock, I can do the job 

As you can see, BASH has no meaning between the team not found and the team that failed.

"- e" is often used to make sure that the shell interpreter stops immediately after an error (so we should think about all the errors ...). This helps prevent a very bad problem when we make a mistake in the script (think about rm -rf "$ v" / * when you forgot to install v ;-)). To do this, we pass the -e option to shebang . Obviously, it is not intended for interactive use, and I cannot imagine the good use of "set -e" or "set + e" (but for testing).

To answer your initial question. You can avoid completing your shell by applying one of the following solutions:

Use if statement

 function myF1() { if git foobar; then echo "I will not print this, because git foobar returned a non-zero exit code" fi } 

Use the control operator & </ h3>

 function myF2() { git foobar && \ echo "I will not print this, because git foobar returned a non-zero exit code" } 

Open subshell

 function myF4() {( set -e git foobar echo "I will not print this, because git foobar returned a non-zero exit code" )} 

In this case, "set -e" will exit the sub-shell immediately, but will not terminate the caller :-)

Using a trap here is not very good, since it can cause a side effect for the caller (the trap is defined globally). Obviously, we can combine a trap and a sub-shell, but this is not useful in your case.

+2
source

Source: https://habr.com/ru/post/969694/


All Articles