Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bash: stop on error in sourced script

Tags:

bash

shell

In a shell script to be executed, I can abort on errors using set -e.

In a sourced script, however, using set -e 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 this would break the parent's set -e if used (which may very well happen if someone wraps my script in the future).

How can I get abort-on-error functionality in a sourced script?

like image 538
slezica Avatar asked Jun 27 '14 20:06

slezica


People also ask

How do I stop a shell script from error?

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.

How do I force stop a bash script?

There are many methods to quit the bash script, i.e., quit while writing a bash script, while execution, or at run time. 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”.

What is $@ in bash?

bash [filename] runs the commands saved in a file. $@ refers to all of a shell script's command-line arguments. $1 , $2 , etc., refer to the first command-line argument, the second command-line argument, etc. Place variables in quotes if the values might have spaces in them.

What is set E in bash?

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.


2 Answers

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

(
    set -e
    source another.sh
)

Only that environment of calling script can never be altered by the called script.

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

like image 171
konsolebox Avatar answered Sep 22 '22 07:09

konsolebox


Well, the question is not very clear re: what the original author wanted after intercepting the error in the sourced script, however, as an entry point for the solution the following will suffice:

You can set a trap on ERR and handle the error inside the sourced script there. Below are two scenarios: one with the sourced script using "set -e" and another with the sourced script NOT using "set -e".

The primary script is calling the secondary script with defined "set -e" and catches 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 primary script is calling the secondary script without "set -e" and catches 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: intercepting an error in the sourced script 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 => ~]$
like image 44
galaxy Avatar answered Sep 18 '22 07:09

galaxy