在我的脚本中,我将数据集拆分为 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 功能)在自己的进程组中运行作业。在bash
、yash
、zsh
、中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
重定向是为了保存日志。你可能不想要它们。