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
函数循环。