In my Bash scripts, I would like to make sure that the script exits as soon as there is an error. (E.g., to avoid a mistaken rm -f *
after a failed cd some_directory
.) For this reason, I always use the -e
flag for bash.
Now, I would also like to execute some cleanup code in some of my scripts. From this blog post I gathered
#!/bin/bash
cd invalid_directory
echo ':('
function clean_up {
echo "> clean_up"
exit 0
}
trap clean_up EXIT
The output I get is
./test.sh: line 3: cd: invalid_directory: No such file or directory
:(
> clean_up
so it does what's advertised. However, when using -e
for bash, I'm only getting
./test.sh: line 3: cd: invalid_directory: No such file or directory
so the script exits without calling clean_up
.
How can I have a bash script exit at all errors and call a clean up script every time?
Bash provides a command to exit a script if errors occur, the exit command. The argument N (exit status) can be passed to the exit command to indicate if a script is executed successfully (N = 0) or unsuccessfully (N != 0).
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.
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.
Using the set -e Option. Bash has this built-in set command to set different options in the shell. One of the many options is errexit. Merely setting this option helps us exit the script when any of the commands return a non-zero status.
You are never reaching the trap
command; your shell exits before the trap is configured.
set -e
clean_up () {
ARG=$?
echo "> clean_up"
exit $ARG
}
trap clean_up EXIT
cd invalid_directory
echo "Shouldn't reach this"
However, it's better to do your own error handling. You often want to vary your behavior depending on the exact reason why your script is exiting, something that is more complicated to do if you are running a single handler for all exits (even if you restrict your trap to ERR
instead of EXIT
).
cd invalid_directory || { echo "cd to invalid_directory failed" >&2; exit 1; }
echo "Shouldn't reach this"
This doesn't mean you have to abandon your clean_up
function. It will still be executed for explicit exits, but it should be restricted to code that should run no matter why your script exits. You can also put a trap on ERR
to execute code that should only be executed if you script is exiting with a non-zero exit status.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With