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

Bef*_*all 9 shell bash python

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

# Execute program on each split file
for part in input_*; do
        python3 $part &
done
wait
Run Code Online (Sandbox Code Playgroud)

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

Sté*_*las 10

您可以使用进程组:

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

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

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

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

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


jim*_*ara 3

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

#!/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
Run Code Online (Sandbox Code Playgroud)

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

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

for i in 2 2 3 4 5 6 7 8 9 10
Run Code Online (Sandbox Code Playgroud)

到:

for part in input_* 
Run Code Online (Sandbox Code Playgroud)

改变:

sleep $i && ls oinkle 
Run Code Online (Sandbox Code Playgroud)

到:

python3 $part 
Run Code Online (Sandbox Code Playgroud)

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