shell脚本中的信号处理

时间:2014-04-04 06:45:20

标签: linux bash shell signals sh

以下是一个shell脚本(myscript.sh)我有:

#!/bin/bash

sleep 500 &

Aprogram arg1 arg2  # Aprogram is a program which runs for an hour.

echo "done"

我在一个终端上启动了这个,我从另一个终端发出了' kill -INT 12345' 。 12345是myscript.sh的pid。

过了一会儿,我发现myscript.sh和Aprogram都死了。但是,< sleep 500&' 仍在运行。

任何人都可以解释为什么会出现这种情况?

另外,当我向' myscript.sh' 发出SIGINT信号时到底发生了什么?为什么' Aprogram' 被杀,为什么不' sleep' ?信号INT如何传输到它的子进程?

3 个答案:

答案 0 :(得分:5)

您在后台启动sleep。因此,杀死脚本时不会被杀死。

如果您想在脚本终止时终止sleep,则需要trap

sleep 500 &
sid=($!)                   # Capture the PID of sleep
trap "kill ${sid[@]}" INT   # Define handler for SIGINT

Aprogram arg1 arg2 & # Aprogram is a program which runs for an hour.
sid+=($!)
echo "done"

现在向您的脚本发送SIGINT也会导致sleep终止。

答案 1 :(得分:2)

  

过了一会儿,我发现myscript.sh和Aprogram都死了。然而'睡觉500&'还在运行。

Aprogram完成后myscript.sh打印“完成”并完成。 sleep 500以PID 1作为父进程获取进程。就是这样。

  

任何人都可以解释为什么会出现这种情况?

Aprogram获取时,SIGINT不会传递给myscript.sh。使用strace确保Aprogram没有收到信号。

  

另外,当我向'myscript.sh'发出SIGINT信号时究竟发生了什么?

我首先想到的情况就像用户按下Ctrl-C并阅读此http://www.cons.org/cracauer/sigint.html一样。但情况并非完全相同。在你的情况下,shell接收到SIGINT但子进程没有。然而,贝壳在那个时刻有一个儿童过程,它没有做任何事情,并一直在等孩子。在将SIGINT发送到等待子进程的shell脚本之后,这是我的计算机上的strace输出:

>strace -p 30484
Process 30484 attached - interrupt to quit
wait4(-1, 0x7fffc0cd9abc, 0, NULL)      = ? ERESTARTSYS (To be restarted)
--- SIGINT (Interrupt) @ 0 (0) ---
rt_sigreturn(0x2)                       = -1 EINTR (Interrupted system call)
wait4(-1,
  

为什么'Aprogram'被杀,为什么不'睡觉'?信号INT如何传输到它的子进程?

据我所知straceAprogram这样的子程序并没有被杀死。它没有收到SIGINT并正常完成。一旦完成你的shell脚本也完成了。

答案 2 :(得分:1)

您需要使用trap来捕获信号:

要忽略SIGINT使用:

trap '' 2

如果你想为此指定一些特殊的动作,你可以将它编成一行:

trap 'some commands here' 2

或更好地将其包装成函数

function do_for_sigint() {
 ...
}

trap 'do_for_sigint' 2

如果您希望允许脚本首先完成所有任务:

keep_running="yes"

trap 'keep_running="no"' 2

while [ $keep_running=="yes" ]; do
 # main body of your script here
done