在多个文件夹中并行运行脚本

use*_*520 7 bash shell-script files parallelism

我在高级目录中有几个子目录。每个子目录都有几个文件和一个 for 循环 shell 脚本。每个子目录中都存在相同的 for 循环脚本。我想进入每个子目录并在多个终端中并行运行 for 循环脚本。我试过这个,但它似乎是连续执行的(一个接一个),但我想并行运行所有这些。

find dir_* -type f -execdir sh for_loop.sh {} \;
Run Code Online (Sandbox Code Playgroud)

Ole*_*nge 6

假设这样做是正确的 - 只有串行:

find dir_* -type f -execdir sh for_loop.sh {} \;
Run Code Online (Sandbox Code Playgroud)

那么你应该能够用以下方法替换它:

find dir_* -type f | parallel 'cd {//} && sh for_loop.sh {}'
Run Code Online (Sandbox Code Playgroud)

要在多个终端中运行它,GNU Parallel 支持tmux在其自己的tmux窗格中运行每个命令:

find dir_* -type f | parallel --tmuxpane 'cd {//} && sh for_loop.sh {}'
Run Code Online (Sandbox Code Playgroud)

它默认为每个 CPU 内核一个作业。在您的情况下,您可能希望运行的作业比核心数多:

 find dir_* -type f | parallel -j+1 --tmuxpane 'cd {//} && sh for_loop.sh {}'
Run Code Online (Sandbox Code Playgroud)

GNU Parallel 是一个通用的并行器,可以很容易地在同一台机器或您可以 ssh 访问的多台机器上并行运行作业。

如果您有 32 个不同的作业要在 4 个 CPU 上运行,一个直接的并行化方法是在每个 CPU 上运行 8 个作业:

简单的调度

GNU Parallel 会在完成后生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:

GNU 并行调度

安装

出于安全原因,您应该使用您的包管理器安装 GNU Parallel,但如果 GNU Parallel 没有为您的发行版打包,您可以进行个人安装,这不需要 root 访问权限。这样做可以在 10 秒内完成:

$ (wget -O - pi.dk/3 || lynx -source pi.dk/3 || curl pi.dk/3/ || \
   fetch -o - http://pi.dk/3 ) > install.sh
$ sha1sum install.sh | grep 883c667e01eed62f975ad28b6d50e22a
12345678 883c667e 01eed62f 975ad28b 6d50e22a
$ md5sum install.sh | grep cc21b4c943fd03e93ae1ae49e28573c0
cc21b4c9 43fd03e9 3ae1ae49 e28573c0
$ sha512sum install.sh | grep da012ec113b49a54e705f86d51e784ebced224fdf
79945d9d 250b42a4 2067bb00 99da012e c113b49a 54e705f8 6d51e784 ebced224
fdff3f52 ca588d64 e75f6033 61bd543f d631f592 2f87ceb2 ab034149 6df84a35
$ bash install.sh
Run Code Online (Sandbox Code Playgroud)

有关其他安装选项,请参阅http://git.savannah.gnu.org/cgit/parallel.git/tree/README

了解更多

查看更多示例:http : //www.gnu.org/software/parallel/man.html

观看介绍视频:https : //www.youtube.com/playlist? list =PL284C9FF2488BC6D1

演练教程:http : //www.gnu.org/software/parallel/parallel_tutorial.html

注册电子邮件列表以获得支持:https : //lists.gnu.org/mailman/listinfo/parallel


dr_*_*dr_ 5

可能最完美的工具是GNU Parallel

parallel ::: dir_*/for_loop.sh
Run Code Online (Sandbox Code Playgroud)

GNU Parallel 不仅并行运行每个作业,而且还对它们的输出进行多路分解,因此它们不会相互干扰。

从它的手册页:

GNU parallel 是一种 shell 工具,用于使用一台或多台计算机并行执行作业。作业可以是单个命令或必须为输入中的每一行运行的小脚本。典型的输入是文件列表、主机列表、用户列表、URL 列表或表列表。作业也可以是从管道读取的命令。GNU parallel 然后可以将输入拆分为多个块,并将一个块通过管道并行传输到每个命令中。

如果您今天使用 xargs 和 tee,您会发现 GNU parallel 非常易于使用,因为 GNU parallel 被编写为具有与 xargs 相同的选项。如果您在 shell 中编写循环,您会发现 GNU parallel 可能能够替换大部分循环,并通过并行运行多个作业使它们运行得更快。

GNU parallel 确保命令的输出与您按顺序运行命令时得到的输出相同。这使得可以使用 GNU parallel 的输出作为其他程序的输入。


Chr*_*phS 3

find不会为你做那件事。

创建一个脚本,找到 for_loop.sh 脚本并执行它们,如下所示:

#!/bin/bash

for theScript in $(find dir_* -name for_loop.sh); do
  "$theScript" &
done
Run Code Online (Sandbox Code Playgroud)

如果脚本必须在子目录内运行,请尝试cd进入之前,也许像cd $(dirname "$theScript") && . $(basename "$theScript").

我的例子没有经过详细测试并且不具有容错性......

编辑1:

正如Sato Katsura正确评论的那样,如果目录名称中有空格,上面的脚本就会中断。

所以我改为循环read

#!/bin/bash
find dir_* -name for_loop.sh | while IFS= read -r theScript; do
  "$theScript" &
done
Run Code Online (Sandbox Code Playgroud)