以下是一个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如何传输到它的子进程?
答案 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如何传输到它的子进程?
据我所知strace
,Aprogram
这样的子程序并没有被杀死。它没有收到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