我可以编写陷阱SIGINT
的shell脚本,但我似乎无法陷阱SIGQUIT
。
#!/bin/bash
function die {
echo "Dying on signal $1"
exit 0
}
trap 'die "SIGINT"' SIGINT
trap 'die "SIGQUIT"' SIGQUIT
while true; do
echo "sleeping..."
sleep 5
done
执行此脚本并按CTRL-C
会产生预期效果,但按CTRL-\
(据我所知,应该触发SIGQUIT
)除了打印^\
之外什么都不做终点站。为什么呢?
我有两个运行理论。第一个是SIGINT
和SIGQUIT
的语义不同,只有SIGQUIT
才会被发送到子进程sleep
,而SIGINT
会被发送到两个进程子进程和父进程bash进程。如果是这种情况,它会在哪里记录?
我的第二个理论是bash不仅默认忽略(即,有一个no-op处理程序)SIGQUIT
(如手册页所示),但不允许它被捕获。这个理论与第一个理论重叠,因为SIGQUIT
可能同时传递给父母和孩子,但父母(bash
)却无法捕获它。如果是这种情况,是否有任何方法在bash脚本中捕获SIGQUIT
?...也许我可以设置一些shopt
?
编辑:这是在运行bash 4.1.5的gnome-terminal 2.32.0上的Ubuntu 10.10上,并且^\
配置为发出SIGQUIT(由stty -a
报告并通过发出{{ 1}} SIGQUIT到其他程序,如^\
)。
更新:
我刚刚发现问题必须以某种方式对gnome-terminal造成影响。如果我从虚拟控制台运行此脚本(即ping
以退出X),当我按ctrl-alt-f1
时,它会完全捕获SIGQUIT。相同的bash和一切,所以唯一的区别必须是终端模拟器。所以现在我的问题变成了:如何在这方面将gnome-terminal配置为像虚拟控制台一样?我^\
在虚拟控制台和gnome-terminal中输出diff
,虽然存在差异,但似乎没有任何直接相关(例如,它们都有stty -a
)。< / p>
更新2:
另一个实验。只需在gnome-terminal中执行quit = ^\;
;按$ sleep 60
,信号无效。现在在虚拟控制台中执行^\
;按$ sleep 60
并且信号被捕获 - 该过程打印^\
并退出。但现在在gnome-terminal中运行Quit
并按$ ping google.com
- 信号将按预期捕获并处理。所以gnome-terminal有一些奇怪的东西,使得SIGQUIT可以被某些程序捕获,但其他人不会捕获,即使其他其他人在从虚拟控制台调用时捕获它。也许我应该升级我的gnome-terminal。
答案 0 :(得分:2)
我只能假设这是gnome-terminal 2.32.0中的某种错误;我已经升级到Ubuntu 11.04,使用gnome-terminal 2.32.1(以及bash 4.2.8),现在SIGQUIT按预期被捕获。
答案 1 :(得分:0)
我在使用XFCE的Fedora 19上观察到相同的行为:根据ps s
,xfce4-terminal中的bash忽略了SIGQUIT,运行yes >/dev/null &
然后ps s
显示甚至是子进程SIGQUIT被忽略了。当我(来自同一终端)运行ssh localhost
时,ssh会话中的shell也忽略了SIGQUIT,但yes >/dev/null &
没有。
鉴于上面提到gnome-terminal的评论,我猜这个bug是在两个终端的公共部分:vte
库。我的是vte-0.28.2-9.fc19.x86_64
。