I have several scripts with while read line
loops that don't execute 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
setting is still in effect. I have many other scripts where my cleanup function works flawlessly. The only time I seem to have a problem is when I press Ctrl-C while the script is in a read
loop. Is there a way to ensure that the cleanup
function will get called when Ctrl-C is pressed while the script is inside a read
loop? Or am I just missing something obvious here?
Update: There is something else going on in my scripts. I ran the exact script above, and I can't get it to fail the way my other scripts do. I will have to try to distill the broken scripts down to something that I can get to fail, at which point I will update the question.
Update 2: Okay, I figured it out. I was getting an error from stty
(which I wasn't seeing because my real cleanup function was also clearing the screen). The error was: stty: standard input: Inappropriate ioctl for device
. I looked this up an apparently it was due to calling stty
while stdin
was redirected from the file /foo/bar
. So I changed my trap
call to trap "break" SIGINT SIGHUP SIGTERM
and it worked.
It turns out the problem was due to the fact that my cleanup
function was calling stty
, and stty
evidently doesn't like to be called while stdin
is being redirected from a file. Thus, when I pressed Ctrl-C while the script was executing the read
loop, the cleanup
function got called as if I had called it from within the loop:
while read -r line; do
...
cleanup
...
done < "$filename"
This, in turn, meant that stty
was executed with a redirected stdin
, and it died with the error stty: standard input: Inappropriate ioctl for device
.
I was able to fix this by changing my trap
line:
trap "break" SIGINT SIGHUP SIGTERM
So instead of having it effectively insert a call to cleanup
into my loop when I press Ctrl-C, it instead just (effectively) inserts a break
into the loop, thus breaking out of the loop and subsequently calling the cleanup
function via the line after the loop.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With