bash robustness: what is a correct and portable way to trap for the purpose of an "on exit" cleanup routine?

Viewed 336

When I create temporary files that I want removed when a script exits, I typically set a trap on EXIT. something like this:

function cleanup ()
{
   if [[ -d "$mytmp" ]]; then rm -rf --one-file-system -- "$mytmp" || :; fi
}

trap cleanup EXIT
...

I recently stumbled upon another script which sets things up slightly differently. It sets up a trap on EXIT, but also on actual signals, i.e.:

function cleanup () { : ... same as above ...; }
trap cleanup EXIT HUP INT QUIT TERM

I'm questioning whether the additional signals in the list are superfluous, or a strict improvement. Are there versions of bash that don't run the EXIT trap on certain signals?

In my experience, CTRL-C (SIGINT) a script will typically also invoke the EXIT trap, even without explicitly trapping on INT. Maybe I've always been lucky and it's just that a child gets killed by SIGINT first, and then the parent script exited with an error (because of set -e or another reason).

What's the best cleanup idiom, in terms of correctness and maybe portability?

Update:

This is tangential to my question, but one portability improvement, pointed out in the comments, is to define functions using the short form: cleanup () { :; } rather than function cleanup () { :; }. Thanks!

1 Answers

I've tested this quite recently on an old bash version (3.2, the one on MacOS from 2007...) and even there it's superfluous.

One could, however, argue that it's there for readability, to signal the reader: "there's no special behavior for any of the signals, just clean up and exit.", because if you have two trap statements referring to the same signal, the one which executed last will override.

Related