Bash script doesn't catch SIGINT while in read loop

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.

链接地址: http://www.djcxy.com/p/78408.html

上一篇: GHC GC'ing火花

下一篇: Bash脚本在读取循环时不捕获SIGINT