我可以编写捕获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不仅默认忽略(即具有无操作处理程序)
SIGQUIT
(如man页面所示),而且根本不允许捕获它。这个理论与第一个理论重叠,因为SIGQUIT
可能会发送到父进程和子进程,但父进程(bash
)无法捕获它。如果是这种情况,在bash脚本中有没有任何方法可以捕获SIGQUIT
?...也许我可以设置一些shopt
吗?编辑:这是在运行bash 4.1.5的gnome-terminal 2.32.0中的Ubuntu 10.10上运行的,并且是的,
^\
配置为发出SIGQUIT(如stty -a
报告的并通过向其他程序(如ping
)发出^\
SIGQUIT进行确认)。更新: 我刚刚发现问题一定与gnome-terminal有关。如果我从虚拟控制台(即
ctrl-alt-f1
以退出X)运行此脚本,则在按下^\
时完美地捕获了SIGQUIT。相同的bash和所有内容,因此唯一的区别必须是终端仿真器。因此,现在我的问题变成了:如何配置gnome-terminal以在这方面像虚拟控制台一样工作?我在虚拟控制台和gnome-terminal中比较了stty -a
的输出,虽然存在差异,但似乎没有立即相关的内容(例如,它们都具有quit = ^\;
)。更新 2: 另一个实验。在gnome-terminal中执行
$ sleep 60
,按下^\
信号不被捕获。现在在虚拟控制台中执行$ sleep 60
,按下^\
信号被捕获--进程会打印Quit
并退出。但是现在在gnome-terminal中运行$ ping google.com
,按下^\
信号被捕获并像预期的那样处理。因此,gnome-terminal有一些奇怪的地方,使得某些程序可以捕获SIGQUIT信号,而其他程序则不能,即使这些其他程序在从虚拟控制台调用时可以捕获它。也许我应该只是升级我的gnome-terminal。
stty
可能没有设置为处理^\
的预期方式。我几乎可以确定 SIGKILL 是唯一无法被捕获的信号。请查看文档。祝好运! - shellterstty -a
命令输出中,quit= 的值是多少?应该是^\
。 - clt60stty -a
的输出如下。对于向其他程序(例如ping
)发送SIGQUIT,^\对我来说绝对有效,该程序通过打印状态行响应SIGQUIT。速度38400波特率; 行24; 列80; 行 = 0; 中断 = ^C; 退出 = ^\; 擦除 = ^?; 杀死 = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; 开始 = ^Q; 停止 = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
- Maxy-B