无法重写 SIGTSTP、SIGTTIN 和 SIGTTOU 的“陷阱命令”

无法重写 SIGTSTP、SIGTTIN 和 SIGTTOU 的“陷阱命令”

我想捕获 SIGTSTP 信号,但我做不到。当我仅调用trap不带参数的命令时,我得到以下结果:

trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU

显然,我的trap有一些已经预先定义的行为。问题是,即使我以 root 身份登录,我也无法重写它。当我使用该trap命令时,这三个信号会被忽略。否则可以正常工作。

我尝试仅通过命令重写它,如下所示:

trap -- 'echo SIGTSTP' SIGTSTP

另一个奇怪的事情是,我能够使用这些信号并且它们正常工作,它们不会被忽略。我可以简单地使用 SIGTSTP 来停止其他进程的工作,并使其再次使用 SIGCONT 继续。

那么,您知道如何重写这些命令吗?您能解释一下这种奇怪的行为吗?


我的操作系统是 Lubuntu 15.04,我使用的是 GNU bash,版本 4.3.30(1)-release (x86_64-pc-linux-gnu)。

答案1

在 Ubuntu 15.04 上使用 bash,它似乎按预期工作......你如何编写脚本?

#!/bin/bash
set -e
trap 'echo TSTP' TSTP
trap 'echo TTIN' TTIN
trap 'echo TTOU' TTOU
trap
while :; do read a; done # wait forever

示例会话(输入 3 次Ctrl+Z然后Ctrl+ C):

$ ./signal.sh
trap -- 'echo TSTP' SIGTSTP
trap -- 'echo TTIN' SIGTTIN
trap -- 'echo TTOU' SIGTTOU
^ZTSTP
^ZTSTP
^ZTSTP
^C

我发现在手册中当 bash 是交互式的并且启用了作业控制时,它会忽略这些信号:

  1. 默认情况下启用作业控制(请参阅作业控制)。当作业控制生效时,Bash 会忽略键盘生成的作业控制信号 SIGTTIN、SIGTTOU 和 SIGTSTP。

您可以通过 禁用作业控制set +m。但是,bash 无论如何都不允许在交互模式下更新处理程序:

$ bash -c trap
$ bash -c 'trap true TSTP && trap'
trap -- 'true' SIGTSTP
$ bash -i -c trap
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
$ bash -i -c 'trap true TSTP && trap'
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU
$ bash -i -c 'set +m && trap true TSTP && trap'
trap -- '' SIGTSTP
trap -- '' SIGTTIN
trap -- '' SIGTTOU

答案2

您没有提到您正在使用哪个 shell,因此如果这是 shell 中的错误,则无法帮助您。

查看 Bourne Shell 手册页:http://schillix.sourceforge.net/man/man1/bosh.1.html您会看到以下文本:

     bolic  names. Any attempt to set a trap on a signal that
     was ignored on entry to the current  shell  is  ineffec-
     tive.  An  attempt  to  trap on signal 11 (memory fault)
     produces an error.code here

所以一切可能都很好,但你的 shell 被调用时忽略了这些信号。

如果您使用的是现代操作系统,您可以调用

 `psig $$`

获取当前 shell 的信号处理,您可以将 $$ 替换为其他进程 ID 以检查其他进程。

相关内容