Bash: stop on error in script source

In an executable shell script, I can abort errors with set -e .

In the original script, however, using set -e , it will kill the original shell if a later command exits with an error status.

 source set_e.sh ./exit_1.sh # shell dies 

A trivial solution would be to set +e at the end of the script, but it could break the parent set -e if it is used (what could happen if someone wraps my script in the future).

How can I get the abort-on-error function in the script source?

+6
source share
5 answers

It's impossible. However, you can choose to use a subshell if you want:

 ( set -e source another.sh ) 

Only this script invocation environment can never be changed by the called script.

Note. It may be important to separate both commands with a new line and not use a semicolon.

+4
source

Change set -e to return 0 (or select your favorite integer instead of 0 ). You can think of it as how to treat your file source as a function. For instance:

 $ cat myreturn.sh #!/bin/bash let i=0 while test "$i" -lt 10; do echo "i $i" if test "$i" -gt 5 ; then return 5 fi sleep 1 ((i+=1)) done return 4 $ ( . myreturn.sh ) i 0 i 1 i 2 i 3 i 4 i 5 i 6 $ echo $? 5 
+3
source

You can check if set -e enabled and conditionally set it after:

 [[ $- == *e* ]] && state=-e || state=+e set -e yourcode set "$state" 

Note, however, that set -e is a bug, and scripts should never depend on it for correctness. For example, if someone from your script sources in an if , set -e might not work correctly:

 echo ' set -e ls file.that.doesnt.exist echo "Success" ' > yourscript set -e if ! source yourscript then echo "Initialization failed" fi echo "Done" 

then set -e will be longer interrupted on failure in yourscript in bash 4.3.30:

 ls: cannot access file.that.doesnt.exist: No such file or directory Success Done 

until it exits the whole script in bash 2, 3 and up to 4.2:

 ls: cannot access file.that.doesnt.exist: No such file or directory 
+2
source

Well, the question is not very clear: what did the author of the original want after catching the error in the script source, however, as an entry point for the solution, it will be enough:

You can set the trap on ERR and handle the error inside the found script. The following are two scenarios: one with a script source using "set -e", and the other with a script source code NOT using "set -e".

The primary script calls the secondary script with the specified "set -e" and detects an error:

 [galaxy => ~]$ cat primary.sh #!/bin/sh set -e echo 'Primary script' trap 'echo "Got an error from the secondary script"' ERR source secondary.sh trap - ERR echo 'Primary script exiting' [galaxy => ~]$ cat secondary.sh #!/bin/sh echo 'Secondary script' set -e echo 'Secondary script generating an error' false echo 'Secondary script - should not be reached' [galaxy => ~]$ ./primary.sh Primary script Secondary script Secondary script generating an error Got an error from the secondary script [galaxy => ~]$ 

The main script calls a secondary script without "set -e" and detects an error:

 [galaxy => ~]$ cat primary.sh #!/bin/sh set -e echo 'Primary script' trap 'echo "Got an error from the secondary script"' ERR source secondary.sh trap - ERR echo 'Primary script exiting' [galaxy => ~]$ cat secondary.sh #!/bin/sh echo 'Secondary script' echo 'Secondary script generating an error' false echo 'Secondary script - should not be reached if sourced by primary.sh' [galaxy => ~]$ ./primary.sh Primary script Secondary script Secondary script generating an error Got an error from the secondary script [galaxy => ~]$ 

As a bonus: catching an error in the script source and continuing:

 [galaxy => ~]$ cat primary.sh #!/bin/sh echo 'Primary script' i=0 while [ $i = 0 ]; do i=1 trap 'echo "Got an error from the secondary script"; break' ERR source secondary.sh done trap - ERR echo 'Primary script exiting' [galaxy => ~]$ cat secondary.sh #!/bin/sh echo 'Secondary script' echo 'Secondary script generating an error' false echo 'Secondary script - should not be reached if sourced by primary.sh' [galaxy => ~]$ ./primary.sh Primary script Secondary script Secondary script generating an error Got an error from the secondary script Primary script exiting [galaxy => ~]$ 
+2
source

You can detect set -o if the errexit parameter was set at the beginning of the script source and restore its original value at the end of the script source.

0
source

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


All Articles