2

在 Linux 上,我想生成一些服务器作为后台服务。

一旦其中一个以退出代码 != 0 终止,他们将被 SIGTERMed,如果他们不想去,则在 3 秒宽限期后被杀死。

按下 Ctrl-C 时也会发生同样的情况。

我想要一个粗略的等价物

set -e
server1 &
server2 &
server3 &
wait (+ kill on error)

(不幸的是,上面的代码没有所有提到的属性。)

儿童不得盗取/逃避 Ctrl-C 信号。

我接受BashPython中的解决方案(使用subprocess)。对于 Python,它们可能只使用标准库函数(我不必先下载模块pip)。如果你有一种很酷的方法可以用另一种语言做到这一点,请不要犹豫,展示它。

如果它也适用于 Mac OS,则可以加分。

4

3 回答 3

1

我不会为您编写解决方案,而是建议在哪里查看: setpgrpwaitpidkill。请注意“儿童不能窃取/逃避 Ctrl-C 信号。” 既不可能(唯一不能回避的信号是SIGSTOPand SIGKILL)也不有意义(你没有SIGINT向他们传递)。

您无法正确执行此操作,bash因为wait等待所有指定的(或者,如果没有指定,则只是所有)进程;您需要“任何”语义,而不是“全部”。

于 2012-04-06T01:11:25.937 回答
0
#!/bin/sh
# Avoid <() process substitutions for portability's sake
set -bm
trap clean SIGCHLD
trap 'kill 0' SIGINT
trap 'sleep 3; kill -9 0' SIGTERM

clean() {
        while read spec pid extra; do
                wait $pid || kill 0
        done << EOF
                $( jobs -l | grep 'Exit\|Done' )
EOF
}

server1 &
server2 &
server3 &
wait
于 2012-04-06T14:18:58.617 回答
0

技术上可以直接在 bash执行此操作,但我不会,因为它需要大量轮询并且效率低且容易出错(基本上您必须kill -0 $pid测试该过程是否仍然存在)。这是一些 bash 代码(来自我身边的一个脚本),它显示了如何记录后台进程 pid:

start_tail() {
    if [ x$TAIL_PID != x ]; then
        echo "internal error: already running tail (pid $TAIL_PID)"
    fi
    tail -0f $1 &
    TAIL_PID=$!
    trap "kill $TAIL_PID" 0 1 2 3 15
}

stop_tail() {
    if [ x$TAIL_PID != x ]; then
        kill $TAIL_PID; trap 0 1 2 3 15
        TAIL_PID=""
    fi
}

在这种特殊情况下,您可能会使用“协同处理”和相当多的黑客攻击使其工作得更好(比上面故意限制的)。

在 Python 中会更容易,但不要使用subprocess; 使用直接操作系统调用(如上面描述的@geekosaur)。@jldupont 对http://supervisord.org/的推荐看起来不错(尤其是因为它是用 Python 编写的)。

于 2012-04-06T08:10:36.387 回答