在 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只能等待它自己的子进程。