脚本不等待循环中的子进程

脚本不等待循环中的子进程

在 bash 脚本中,我遍历文件夹查找一些文件,如果找到它们,我会调用包含这些文件的目录的函数。见下文

pairedread $1 &
pairedread $2 &
pairedread $3 & 
wait
echo "Done ..."

echo 
echo "======================"
echo "Testing again"
echo "======================"
echo

find . -type d -print | while read DIR; do
    echo "reading..."
    test -r "$DIR"/*_1.gz -a -r "$DIR"/*_2.gz || continue
    ( pairedread $DIR &  )
    done

wait
echo "Done..."

pairedread是获取文件夹并对给定目录中的文件调用 python 脚本的函数。在第一种情况下,IE当我明确给出包含感兴趣的文件的文件夹时,脚本会运行pairedread执行实例并最终终止,然后显示有用的消息"Done..." 所有子流程完成。

在第二种情况下,选择相同的三个目录并创建pairedread 的三个实例。但是,脚本根本不等待,它会"Done..."立即打印并在子进程在后台运行时返回。

我错过了什么吗?为什么我不能等待子流程完成后再继续执行脚本?

答案1

因为您在子 shell 中启动这些进程(因为管道和额外(...)选项),所以wait不知道有任何子进程要等待。您可以重写该循环,这样它就不需要像以下这样的子 shell:

while read DIR; do
    echo "reading..."
    test -r "$DIR"/*_1.gz -a -r "$DIR"/*_2.gz || continue
    pairedread $DIR &
done < <(find . -type d -print)

Wait 只知道当前进程的子进程。当您使用它时|,它会为部件创建一个子外壳,以将侧面的标准输入/标准输出连接在一起。在子 shell 中启动的任何进程都不是“顶级”进程的子进程,因此wait不知道它们。

pairedread因此,在这种情况下,您会因为使用语法在子 shell 中显式启动以及在管道中的循环()块内发生而受到阻碍。while

重写该块以避免管道并删除显式子 shell 让外部wait了解子进程,从而执行您期望的操作

答案2

正如@Eric 指出的那样,如果您想等待进程,则需要在管道之外进行后台处理,而不是对命令进行子 shell 处理。

双fork:当你至少进行两次fork时,该进程将成为孤立进程,并且init进程将成为该进程的父进程。

你的代码:你做了三个fork(管道,子shell和后台),因此,init进程成为你新启动的进程的父进程,你不能等待它,因为wait只能等待它自己的子进程。

相关内容