why is this simple bash trap failing

bash, bash-trap, shell-trap

Solution

I just tried it (on an ancient RHEL Linux with bash 3.2.25) and saved your code in `trap.sh`, ran `bash trap.sh`, and got:

 Sleeping for 5 seconds, hit ctrl-c to proceed now.

followed by:

No time for napping!

when I interrupted, as you expected. When I let it run without interrupting, I got the expected message:

Naptime over.

You then commented:

At least I know it should work as expected. I'm using the latest version of Tinycore Linux with GNU bash, version 4.0.33(1)-release (i686-pc-linux-gnu). Upon opening a new terminal, `declare -f nonap` and `trap` both return no output. After running this script and getting the "Naptime over." output, `trap` returns `trap -- 'nonap' SIGINT` and `declare -f nonap` returns the function as defined in my script.

To which I responded:

How are you running this script, then? Using `source` or `.` to read it? Ah, yes; you must be. I just tried that, and the interrupt while sourcing gave me `Naptime over.`; typing another interrupt though gave me `No time for napping!` and the shell exited. The second time it behaved as expected; I'm not sure what's up with the interrupt while dotting the script. That is unexpected behaviour.

Why did you want to source or dot this? Why not just use it as a plain old script?

No reason to source...I was just using that to run it while testing. I guess I've never run into any anomalies like this when using . before, but I'm still a newb too. I am seeing the same results you are, and it works as expected on the first interrupt if I run it with bash.

Well, there's a "Doctor, Doctor, it hurts when I hit my head against the wall" component to the following advice, but there's also basic pragmatism in there too.

You use `source` (in C shell or `bash`) or `.` (in Bourne, Korn, POSIX shells or `bash`) to have the script affect the environment of the invoking shell, rather than running as a sub-shell. The giveaway to solving the problem (albeit largely by fluke) was when you reported that after running the script, you had the function defined; that can't happen unless you were using `source`. In this case, it is fairly clear that you do not want the `trap` set in the calling shell. When I ran it (from a `ksh` with prompt `Toru JL:`), I got:

Toru JL: bash
bash-3.2$ trap
bash-3.2$ source trap.sh
Sleeping for 5 seconds, hit ctrl-c to proceed now.

Naptime over.
bash-3.2$ trap
trap -- 'nonap' INT
bash-3.2$ No time for napping!
Toru JL: 

The 'No time for napping!' message appeared when I hit the interrupt key again, and it terminated the `bash` I'd run. If you continue to use it with `source`, you would want to add `trap INT` to the end of the script, and you might also want to undefine the the function.

However, you are much better off isolating it all in a shell and running it as a sub-process, I think.

But...your finding that this sort of thing plays funny games when the script is sourced is interesting. It's a minor anomaly in the behaviour of `bash`. I'm not sure it rises to the level of 'bug'; I'd have to read a lot of manual rather carefully (probably several times) and consult with other knowledgeable people before claiming 'bug'.

I'm not sure it will be any consolation, but I tried `ksh` on your script with `.` and it worked as we'd both expect:

Toru JL: ksh
$ . trap.sh
Sleeping for 5 seconds, hit ctrl-c to proceed now.
No time for napping!
Toru JL: 

Problem

I'm still pretty new to bash scripting, and I'm having a hard time figuring out why this simple trap is not working as expected. Goal - create an optional waiting period that can be skipped by pressing CTRL+C. Expected result of pressing CTRL+C - immediately echo "No time for napping!" and exit. Actual result of pressing CTRL+C - immediately echo "naptime over." and exit. ``` #!/bin/bash nonap() { echo "No time for napping!" exit } trap nonap INT echo "Sleeping for 5 seconds, hit ctrl-c to proceed now." sleep 5 echo "Naptime over." ``` Why is my trap function not invoked?

Original source