I have a script I wrote in Bash that I'm trying to modify to be POSIX-compliant. I have managed to get everything working except I cannot get the EXIT trap to trigger when the process is terminated with killall, CTRL+C or closing the terminal - as it did with Bash. Here is my exit trap:


TMP=$(mktemp /tmp/countdown.XXXXX)
trap 'rm -rf $TMP' EXIT
  • Is there still something that does not work by Kusalananda's answer?
    – jarno
    Feb 10, 2020 at 12:40

3 Answers 3


In a strictly POSIX shell, the EXIT trap is evaluated before the shell exits due to executing exit or due to executing the last command in a script. It is not executed if the shell exits due to a signal.

Would you want to catch Ctrl+C, you would have to trap INT (the "interrupt" signal). If closing the terminal sends the script a HUP ("hang-up") signal, you would have to trap that too.

trap 'rm -rf "$TMP"; trap - EXIT; exit' EXIT INT HUP

You may also want to trap TERM, the generic "terminate" signal sent by default by kill.

The trap above explicitly resets the EXIT trap so that it's not called again when the script exits due to receiving one of the listed signals.

  • about exit in a SIGINT trap: unix.stackexchange.com/search?q=wait+and+cooperative+exit
    – user313992
    May 21, 2019 at 0:16
  • I guess you should trap even more signals, that have terminate as default action, but signal POLL did not work with dash.
    – jarno
    Apr 24, 2021 at 12:28
  • @jarno The built-in kill utility can be used to test what signals the shell understands: dash -c 'kill -l'. I have personally never heard of a POLL signal.
    – Kusalananda
    Apr 24, 2021 at 12:44

As mentioned by Kusalananda, EXIT does not trap signals in POSIX. The simplest solution is to add something like this to your code:

trap exit INT HUP TERM

This will catch the signals you want and call your original trap when it reaches the exit statement.


Just remove the temporary file immediately after creating it, and read & write to it via a file descriptor.

Pass it as /dev/fd/[fd] or /proc/self/fd/[fd] to commands which expect a path.


t=$(mktemp); exec 5<>"$t"; rm "$t"

echo some text >&5
exec 5<>/dev/fd/5   # rewind / seek back at the start of the file
cat <&5

cmd1 /dev/fd/5  # cmd1 only takes paths
cmd2 5>&-       # don't leak fd 5 to cmd2

You can also open the tempfile as multiple separate fds, as in exec 5<"$t" 6>"$t".

The rewind trick is linux-only; I cannot think of any portable way of doing it; ideas are welcome ;-\

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .