2011-05-27 32 views
4

我有一个bash shell脚本S1,它同步启动另一个shell脚本S2(仅包含sleep 20),即在前台。通过发送信号在后台停止shell脚本

我想是这样的:

当我送SIGTERM或SIGINT到S1,既S1S2应该停止。

实际上,如果我在前台命令行上启动S1,并且按CTRL-C(不管是否明确地捕获脚本中的SIGINT),它都可以工作。

当我开始在后台S1,然后用kill -s SIGINT $!它需要发送SIGINT信号直到S2终止其正常的处理,即S2不中断。

我的使用案例是后者,我需要一种方法来通过发送一个信号S1S2只需S1

+0

寻找'[unix] SIGINT'返回了许多有希望的答案。特别是http://stackoverflow.com/questions/4042201/how-does-sigint-relate-to-the-other-termination-signals。祝你好运。 – shellter 2011-05-27 14:39:50

回答

2

S1.sh:

#!/bin/sh 

on_term() 
{ 
    echo "S1: Sending TERM to S2.sh" 
    pkill -TERM S2.sh 
    echo "S1: Waiting for S2 to complete..." 
} 

trap "on_term" TERM 

echo "S1: Forking a child..." 

./S2.sh & 

while [ 1 == 1 ]; do 
    wait 
    if [ $? -eq 0 ]; then 
     break 
    fi 
done 

echo "S1: Done!" 

S2.sh:

#!/bin/sh 

on_term() 
{ 
    echo "S2: Terminating..." 
    exit -1 
} 

trap "on_term" TERM 

echo "S2: Sleeping..." 

sleep 5 

echo "S2: Done!" 

玩得开心!

+0

您应该使用'$!'而不是关闭具有特定名称的进程。 – jilles 2011-05-27 10:53:25

+0

嗯,这只是一个例子;) – 2011-05-27 11:19:45

+0

当然,在后台开始S2是一个解决方案。但是,如果不在后台启动S2,我可以达到相同的效果吗?为什么行为与上面描述的不同(当S1在前台运行时ctrl-c与S1在后台启动时的“kill -s SIGINT”)? – Armin 2011-05-27 11:41:07

2

如果从命令行启动S1,则使用以%开头的作业规范(例如kill -INT %+)将信号发送到进程组中的所有进程。

如果从另一个脚本S3开始S1,或许应该用S1S2SIGINT终止,从而减少上述情况。否则,你可以尝试使用像

set -m 
S1 & 
set +m 
pid=$! 
... 
kill -INT -- -$pid 

作业控制,但是这可能不是所有的炮弹可靠地工作,或者如果没有控制终端。按照Ilya的答案手动转发信号是另一种选择。