Nico Schlömer
Nico Schlömer

Reputation: 58761

Bash: Exit and cleanup on error

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?

Upvotes: 16

Views: 17874

Answers (1)

chepner
chepner

Reputation: 531055

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.

Upvotes: 30

Related Questions