Bash线程:等待所有工作线程完成不起作用?

Gar*_*uth 12 bash multithreading

我正在编写一个小脚本,它将在主线程中创建存档,并且在每个存档完成后,将通过调用函数创建一个新线程,该函数将负责上传这些存档.我希望在后台完成上传的原因是,在上载以前的档案时可以创建另一个档案.

我遇到的问题是在脚本的最后.也就是说,主线程不会等待所有上传线程在退出之前完成.查看以下简化脚本(我删除/更改了与问题无关的代码部分)

function func {
for files in /home/somewhere/
  do
    echo "Uploading $1" &
  done
wait
}

find /home/some/path -type f | while read filename ; do
  echo "Creating archive of $filename"
  func $somevariable &
done

wait
Run Code Online (Sandbox Code Playgroud)

在创建最后一个存档之前,一切都很好地执行,然后脚本在所有func线程完成之前结束,留下许多文件未上传.

谢谢你的想法.

Dig*_*oss 13

更新:评论中的好点.

所以,再看看,问题是管道创建的子shell到循环.这是构建脚本的好方法,但是你需要在shell中进行最后的等待,从而分离出后台任务.

所以做这样的事情:

find /home/some/path -type f | (while read filename; do
    echo "Creating archive of $filename"
    func $somevariable &
  done
  wait
)
Run Code Online (Sandbox Code Playgroud)


dub*_*jim 6

整蛊!问题是这块

find /home/some/path -type f | while read filename ; do
  ...
done
Run Code Online (Sandbox Code Playgroud)

创建一个子shell.func $ somevariable作业在子shell中创建.父shell看到创建的所有后台作业都已完成,它不会跟踪由它生成的子shell创建的后台作业.

最简单的解决方法是从父shell创建后台作业.您可以通过不使用管道来避免创建子shell:

while read filename ; do
  ...
done < <(find /home/some/path -type f)
Run Code Online (Sandbox Code Playgroud)

好吧,这会为查找创建一个子shell--但是while块不再是子shell.

请注意,上述内容仅适用于bash.(不知道ksh或zsh,也许它也适用于那里.但它不会在灰和其他sh衍生物下工作.)