我想捕获 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 是交互式的并且启用了作业控制时,它会忽略这些信号:
- 默认情况下启用作业控制(请参阅作业控制)。当作业控制生效时,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 以检查其他进程。