如何在bash脚本中正确捕获SIGQUIT?

时间:2011-06-17 04:32:44

标签: bash unix signals exit bash-trap

我可以编写陷阱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?...也许我可以设置一些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。

2 个答案:

答案 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