如何在Linux上使用bash进行陷阱/杀死?

时间:2013-01-07 13:59:23

标签: bash

我的示例文件

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。我对这种行为感到很困惑,是不是?

3 个答案:

答案 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()函数。