我可以很好地编写陷阱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不仅在默认情况下(如手册页所示)忽略(即,有一个no-op处理程序)SIGQUIT,而且根本不允许它被捕获。这个理论与第一个理论重叠,因为它可能是SIGQUIT同时适用于父代和子代的情况,但是父代(bash)无法捕获它。如果是这样,有没有办法在bash脚本中捕获SIGQUIT?... 也许我可以设定一些?
编辑:这是在运行bash 4.1.5的gnome终端2.32.0中的Ubuntu 10.10上,yesshopt被配置为发出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/

10-11 18:16