如果任何生成的子进程失败,则杀死所有子进程并退出

如果任何生成的子进程失败,则杀死所有子进程并退出

在我的脚本中,我将数据集拆分为 input_aa、input_ab 等。然后,我通过相同的 Python 脚本运行每个数据集,如下所示:

# Execute program on each split file
for part in input_*; do
        python3 $part &
done
wait

我的问题有两个:如何检测 Python 进程失败,以及当检测到时,如何杀死所有生成的子进程并以失败退出脚本?

答案1

您可以使用进程组:

set -m
(
   for part in input_*; do
     (python3 "$part" || kill 0) &
   done
   wait
)

set -m(以及可选的 POSIX shell 功能、必需的 Unix shell 功能)在自己的进程组中运行作业。在bashyashzsh、中mksh,这是启用的子 shell 的作业,set -m因此外部进程(...)和其中创建的所有进程将被放置在同一个进程组中。

对于dash其他ash基于 shell 的情况,这只适用于顶级 shell 进程。因此,除非将代码放入子 shell 中,否则该代码将起作用。

ksh这在 AT&T或旧的 SysV/Bourne shell 中根本不起作用。

kill 0向当前进程组的所有成员发送 SIGTERM 信号。

答案2

这是一个例子。首先尝试一下以获得您所需要的东西。它不能按原样破坏太多。

#!/bin/bash
# Example of killing off all children

> killfile
> outfile.err
kill_em()
{
   echo 'killing all children ' > 2
   while read pid
   do
      kill -0 $pid && kill -9 $pid  # if still running kill it
   done < killfile
   exit 1
}

export grandparentpid=$$
trap 'kill_em' 6
for i in 2 2 3 4 5 6 7 8 9 10
do
        ( sleep $i && ls oinkle  >> outfile 2>> outfile.err &
          pid=$!
          echo $pid >> killfile
          wait $!
          [ $? -ne 0 ] && kill -6 $grandparentpid
        ) &
done
wait

这是故意设置失败,因为ls oinkle会失败(在我的计算机上)。

当你在修改启动脚本后得到你需要的东西时---更改:

for i in 2 2 3 4 5 6 7 8 9 10

到:

for part in input_* 

改变:

sleep $i && ls oinkle 

到:

python3 $part 

重定向是为了保存日志。你可能不想要它们。

相关内容