我的示例文件
traptest.sh:
#!/bin/bash
trap 'echo trapped' TERM
while :
do
sleep 1000
done
Run Code Online (Sandbox Code Playgroud)
$ traptest.sh&
[1] 4280
$ kill%1 < - 按作业号码杀死
终止
被困
$ traptest.sh&
[1] 4280
$ kill 4280 < - 按进程ID杀死不起作用?
(蟋蟀的声音,过程没有被杀死)
如果我完全删除了trap语句,kill process-id会再次运行吗?
在工作中运行一些RHEL 2.6.18-194.11.4.el5.我对此行为感到困惑,是不是?
这是预期的行为.您发送的默认信号kill是SIGTERM陷阱.考虑一下:
#!/bin/bash
# traptest.sh
trap "echo Booh!" SIGINT SIGTERM
echo "pid is $$"
while : # This is the same as "while true".
do
a=1
done
Run Code Online (Sandbox Code Playgroud)
(睡觉确实创造了一个新的过程,我的例子我的行为更清晰).
因此,如果您traptest.sh在一个终端和kill TRAPTEST_PROCESS_ID另一个终端中运行,运行traptest的终端输出将按Booh!预期进行(并且该进程不会被终止).如果你尝试发送kill -s HUP TRAPTEST_PROCESS_ID,它将杀死traptest进程.
这应该可以消除%1困惑.
注意:代码示例取自tldp
kill [pid]
Run Code Online (Sandbox Code Playgroud)
将TERM信号专门发送到指定的PID.
kill %1
Run Code Online (Sandbox Code Playgroud)
将TERM信号发送到作业#1的整个进程组,在这种情况下发送到脚本pid +他的孩子(睡眠).
我已经通过strace on sleep进程和脚本进程验证了这一点
无论如何,有人在这里遇到了类似的问题(但使用SIGINT而不是SIGTERM):http://www.vidarholen.net/contents/blog/?p = 34 .
引用最重要的一句话:
kill -INT%1将信号发送到作业的进程组,而不是后台的pid!
kill %<jobspec>Davide Berra 解释了和之间的差异kill <PID>,但没有解释这种差异如何导致您观察到的结果。毕竟,Unix 信号处理程序应该几乎立即被调用,那么为什么SIGTERM单独向脚本发送 a 不会触发其陷阱处理程序呢?
如果
bash正在等待命令完成并接收到已设置陷阱的信号,则在命令完成之前不会执行陷阱。
因此,信号立即传递,但处理程序的执行被推迟到sleepexited。
因此,与kill %<jobspec>:
sleep收到的SIGTERMbash注册信号,注意到为trap它设置了 a,并将处理程序排队以供将来执行sleep立即退出bash注意到sleep的退出,并运行陷阱处理程序而与kill <script_PID>:
SIGTERMbash注册信号,注意到为trap它设置了 a,并将处理程序排队以供将来执行sleep1000 秒后退出bash注意到sleep的退出,并运行陷阱处理程序显然,您不想花足够长的时间来看到最后一点。:)
如果您对具体细节感兴趣,请下载bash源代码并查看trap.c,特别是trap_handler()和run_pending_traps()函数。