我可以很好地编写陷阱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
?... 也许我可以设定一些?编辑:这是在运行bash 4.1.5的gnome终端2.32.0中的Ubuntu 10.10上,yes
shopt
被配置为发出SIGQUIT(由^\
报告,并通过向stty -a
等其他程序发出^\
SIGQUITs来确认)。更新:
我刚刚发现这个问题一定是由于gnome终端造成的。如果我从一个虚拟控制台运行这个脚本(即,
ping
以脱离X),当我按下ctrl-alt-f1
时,它会很好地捕获SIGQUIT。同样的bash和所有东西,所以唯一的区别必须是终端模拟器。所以现在我的问题变成了:如何配置gnome终端在这方面表现得像虚拟控制台?我在虚拟控制台和gnome终端中看到了^\
的输出,虽然存在差异,但似乎没有直接相关的东西(例如,它们都有diff
)。更新2:
另一个实验。只需在gnome终端中执行
stty -a
;按quit = ^\;
,信号就不会被察觉。现在,在虚拟控制台中执行$ sleep 60
;按下^\
并捕获信号——进程打印退出。但现在在gnome终端中运行$ sleep 60
,然后按^\
——信号被捕获并按预期处理。因此,gnome终端有一些奇怪的地方,比如SIGQUIT可以被一些程序捕获,但不能被其他程序捕获,即使其他程序在从虚拟控制台调用时确实捕获了它。也许我应该升级我的gnome终端。 最佳答案
我只能假设这是gnome终端2.32.0中的某种错误;我已经升级到Ubuntu11.04,gnome终端2.32.1(和Bash4.2.8)和SIGQUIT现在被困在预期之中。
关于bash - 如何在bash脚本中正确捕获SIGQUIT?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/6381353/