Bash script does not capture SIGINT during read cycle

I have several scripts with while read line loops that do not perform my cleanup function when I press Ctrl C. For example:

 #!/bin/bash cleanup() { stty echo exit 0 } trap cleanup SIGINT SIGHUP SIGTERM stty -echo while read -r line; do echo "$line" done < /foo/bar cleanup 

When I press Ctrl-C, my terminal is screwed up because the stty -echo parameter is still valid. I have many other scripts where my cleanup function works flawlessly. The only time I have a problem is when I press Ctrl-C and the script in the read loop. Is there a way to ensure that the cleanup function is called when Ctrl-C is pressed while the script is inside the read loop? Or am I just missing something obvious here?

Update: Something is happening in my scripts. I have executed the exact script above, and I cannot make it fail, as my other scripts do. I will have to try to redo the broken scripts into something that I may crash, and at that moment I will update the question.

Update 2: Ok, I figured it out. I was getting the stty error message (which I did not see because my real cleanup function also cleared the screen). Error: stty: standard input: Inappropriate ioctl for device . I looked at this, apparently due to a call to stty , and stdin was redirected from the file /foo/bar . So I changed my trap call to trap "break" SIGINT SIGHUP SIGTERM , and it worked.

+7
bash shell
source share
1 answer

It turns out the problem was that my cleanup function called stty , and stty apparently doesn't like to be called, and stdin redirected from the file. Thus, when I pressed Ctrl-C while the script was executing the read loop, the cleanup function was called as if I had called it from the loop:

 while read -r line; do ... cleanup ... done < "$filename" 

This, in turn, meant that stty was executed with a redirected stdin , and he died with the error stty: standard input: Inappropriate ioctl for device .

I was able to fix this by changing the trap line:

 trap "break" SIGINT SIGHUP SIGTERM 

Therefore, instead of effectively inserting a cleanup call into my loop when I press Ctrl-C, instead it simply (efficiently) inserts a break into the loop, thereby breaking out of the loop and then calling cleanup through the line after the loop.

+4
source share

All Articles