So section 5 from here made sense to me and I wanted to implement it. I have this bash script

#!/usr/bin/env bash

cp aux.sh aux.sh.bak

cleanup() {
    cp aux.sh.bak aux.sh
    rm -rf aux.sh.bak

trap 'cleanup; trap - SIGINT; kill -s SIGINT "$$"' SIGINT
trap cleanup EXIT

echo "Hold this for now" >> aux.sh

read -rp "Hit Enter to finish"

exit 0

But, when running it, if I press Ctrl+C I get a this error:

Hit Enter to finish^Ccp: cannot stat 'aux.sh.bak': No such file or directory

I don't know why this error happens. But my guess is that cleanup is being run again as a result of the kill command.

What am I doing wrong? How to do this properly?

1 Answer 1


In bash, EXIT traps are invoked regardless of the exit cause. In your case, CtrlC causes the SIGINT trap to run, then when the script kills itself, the EXIT trap runs.

As you suspect, the cleanup function thus ends up being called twice.

The wiki page you referred to explains how to deal with this (in bash only):

So to clean up, just trap EXIT and call a cleanup function from there. Don't trap a bunch of signals.

  • This is working: trap 'trap SIGINT; kill -s SIGINT "$$"' SIGINT; trap cleanup EXIT
    – leo
    May 1, 2023 at 21:50
  • I’m curious: what’s the use of the SIGINT trap? There doesn’t seem to be much point in it if all it does is untrap and resend the signal. May 2, 2023 at 4:43
  • If I don’t trap it, <kbd>Ctrl</kbd> <kbd>C</kbd> kills whatever command my script is running at the moment but it will not kill the script which is undesirable in my case.
    – leo
    May 2, 2023 at 22:54
  • That’s surprising, the default behaviour in bash is to exit scripts if a command they run is stopped with Ctrl-C. Perhaps the command in question in your case isn’t setting its exit information correctly... May 3, 2023 at 4:31
  • That is probable, yes.
    – leo
    May 6, 2023 at 0:39

You must log in to answer this question.

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