如何在Bash脚本中正确捕获SIGQUIT信号?

5

我可以编写捕获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)除了在终端中打印^\之外什么也不做。为什么?
我有两个理论。第一个是SIGINTSIGQUIT的语义不同,因此只有将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。

这在我的Ubuntu 11.04,bash 4.2.8上按预期工作。您使用的是哪个操作系统和bash版本? - Gustavo Giráldez
对我也有效。正在睡觉... ^\退出(核心已转储) 因信号SIGQUIT而死亡 - Jasonw
这里有许多关于“陷阱 trap”的帖子。请查看。此外,我认为您的 stty 可能没有设置为处理 ^\ 的预期方式。我几乎可以确定 SIGKILL 是唯一无法被捕获的信号。请查看文档。祝好运! - shellter
你的脚本在我的OS X 10.6.7上运行良好,bash版本为4.2.0(1)-release (i386-apple-darwin10.7.0)。 - clt60
1
你的 stty -a 命令输出中,quit= 的值是多少?应该是 ^\ - clt60
这是在Ubuntu 10.10,bash 4.1.5上运行的,并且stty -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
2个回答

3

我只能猜测这可能是gnome-terminal 2.32.0中的某种错误;我已经升级到Ubuntu 11.04,使用gnome-terminal 2.32.1(和bash 4.2.8),现在SIGQUIT被正常捕获。


0

我在 Fedora 19 上的 XFCE 中观察到相同的行为:根据 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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接