我的示例文件
traptest.sh:
#!/bin/bash
trap 'echo trapped' TERM
while :
do
sleep 1000
done
$ 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。我对这种行为感到很困惑,是不是?
答案 0 :(得分:8)
这是预期的行为。 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
(睡觉确实创造了一个新的过程,我想我的例子,行为更清晰。)
因此,如果您在一个终端中运行traptest.sh
而在另一个终端中运行kill TRAPTEST_PROCESS_ID
,则运行traptest的终端输出将按预期Booh!
进行(并且该过程将 NOT < / strong>被杀)如果您尝试发送kill -s HUP TRAPTEST_PROCESS_ID
,它将会终止陷阱测试过程。
This应该清除%1
混淆。
注意:代码示例取自tldp
答案 1 :(得分:7)
kill [pid]
将TERM信号专门发送到指定的PID。
kill %1
将TERM信号发送到作业#1的整个进程组,在这种情况下发送到脚本pid +他的孩子(睡眠)。
我已经通过strace on sleep进程和脚本进程验证了
无论如何,有人在这里遇到了类似的问题(但使用SIGINT而不是SIGTERM):http://www.vidarholen.net/contents/blog/?p=34。
引用最重要的一句话:
kill -INT%1将信号发送到作业的进程组,而不是背景的pid!
答案 2 :(得分:1)
Davide Berra解释了kill %<jobspec>
和kill <PID>
之间的差异,但 这种差异是否会导致您观察到的内容。毕竟,Unix信号处理程序应该被即时调用,那么为什么单独向脚本发送SIGTERM
不会触发其陷阱处理程序?
bash
手册页在the last paragraph of the SIGNALS section中解释了原因:
如果
bash
正在等待命令完成并收到信号 已经设置了陷阱,陷阱将不会执行,直到 命令完成。
因此,信号 立即传递,但处理程序执行推迟到sleep
退出。
因此,kill %<jobspec>
:
sleep
都收到SIGTERM
bash
注册了该信号,注意到为其设置了trap
,并将处理程序排队等待将来执行sleep
立即退出bash
注意sleep
退出,并运行了陷阱处理程序而kill <script_PID>
:
SIGTERM
bash
注册了该信号,注意到为其设置了trap
,并将处理程序排队等待将来执行sleep
在1000秒后退出 bash
注意sleep
退出,并运行了陷阱处理程序显然,你没有足够长的时间去看最后一点。 :)
如果您对血腥详情download the bash
source code感兴趣,请查看trap.c
,特别是trap_handler()
和run_pending_traps()
函数。