通过发送信号在后台停止shell脚本

时间:2011-05-27 09:25:16

标签: bash signals

我有一个bash shell脚本S1,可以同步启动另一个shell脚本S2(仅包含sleep 20),即在前台。

我想要的是以下内容:

当我向S1发送SIGTERM或SIGINT时,S1S2都应该停止。

实际上,如果我在前台命令行启动S1,如果按CTRL-C(无论是否在脚本中明确地捕获SIGINT),这都有效。

当我在后台启动S1然后向其发送带有kill -s SIGINT $!的SIGINT信号时,直到S2终止其正常处理,即S2不会被中断。

我的用例是后者,我需要通过向S1发送信号来中断S2S1

2 个答案:

答案 0 :(得分: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!"

玩得开心!

答案 1 :(得分:2)

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

如果您从其他脚本S1开始S3,则可能会在S1上以S2SIGINT终止,这会减少到上述内容。否则,您可以尝试使用

之类的作业控制
set -m
S1 &
set +m
pid=$!
...
kill -INT -- -$pid

但是对于所有shell,或者如果没有控制终端,这可能无法可靠地工作。如在Ilya的答案中手动转发信号是另一种选择。