Bash脚本在读取循环时不捕获SIGINT
当我按Ctrl C时,我有几个脚本while read line循环时不会执行我的清理功能。例如:
#!/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
当我按下Ctrl-C时,由于stty -echo设置仍然有效,我的终端被搞砸了。 我有许多其他脚本,我的清理功能完美无瑕。 我似乎遇到问题的唯一时间是在脚本处于read循环时按Ctrl-C。 有没有办法确保当脚本在read循环中时按下Ctrl-C时cleanup函数会被调用? 或者我在这里错过了一些明显的东西?
更新:我的脚本中还有其他内容正在发生。 我运行了上面的确切脚本,并且我无法让它以我其他脚本的方式失败。 我将不得不尝试将破损的脚本提炼出来,以便我可以失败,此时我会更新问题。
更新2:好的,我明白了。 我从stty中得到一个错误(我没有看到,因为我的真正清理功能也清除了屏幕)。 错误是: stty: standard input: Inappropriate ioctl for device 。 我查看了一下,显然这是由于在stdin从文件/foo/bar重定向时调用stty 。 所以我改变了我的trap调用trap "break" SIGINT SIGHUP SIGTERM ,它的工作。
事实证明,问题是由于我的cleanup函数调用了stty , stty显然不喜欢在stdin从文件重定向时调用。 因此,当我在脚本执行read循环时按Ctrl-C时, cleanup函数被调用,就好像我已经从循环中调用它:
while read -r line; do
...
cleanup
...
done < "$filename"
这反过来又意味着stty被重定向的stdin执行,并且它以错误stty: standard input: Inappropriate ioctl for device而死stty: standard input: Inappropriate ioctl for device 。
我可以通过改变我的trap线来解决这个问题:
trap "break" SIGINT SIGHUP SIGTERM
因此,当我按下Ctrl-C时,它不是有效地将一个调用cleanup插入到我的循环中,而是只是(有效地)在循环中插入一个break ,从而打破循环并随后通过行后调用cleanup函数循环。
