我在高级目录中有几个子目录。每个子目录都有几个文件和一个for循环shell脚本。每个子目录中都存在相同的 for 循环脚本。我想进入每个子目录并在多个终端中并行运行 for 循环脚本。我尝试了这个,但它似乎是串行执行的(一个接一个),但我想并行运行所有这些。
find dir_* -type f -execdir sh for_loop.sh {} \;
答案1
假设这做了正确的事情 - 仅以串行方式:
find dir_* -type f -execdir sh for_loop.sh {} \;
那么你应该能够将其替换为:
find dir_* -type f | parallel 'cd {//} && sh for_loop.sh {}'
要在多个终端中运行它,GNU Parallel 支持在其自己的窗格tmux
中运行每个命令:tmux
find dir_* -type f | parallel --tmuxpane 'cd {//} && sh for_loop.sh {}'
默认情况下,每个 CPU 核心执行一项作业。在您的情况下,您可能希望比您拥有的核心多运行一项作业:
find dir_* -type f | parallel -j+1 --tmuxpane 'cd {//} && sh for_loop.sh {}'
GNU Parallel 是一个通用并行器,可以轻松地在同一台计算机或多台您可以通过 ssh 访问的计算机上并行运行作业。
如果您想要在 4 个 CPU 上运行 32 个不同的作业,则并行化的直接方法是在每个 CPU 上运行 8 个作业:
相反,GNU Parallel 在完成后会生成一个新进程 - 保持 CPU 处于活动状态,从而节省时间:
安装
出于安全原因,您应该使用软件包管理器安装 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
对于其他安装选项,请参阅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
答案2
也许最完美的工具是GNU 并行:
parallel ::: dir_*/for_loop.sh
GNU Parallel 不仅并行运行每个作业,而且还对它们的输出进行多路分解,这样它们就不会互相干扰。
从其手册页:
GNU并行是一种shell工具,用于使用一台或多台计算机并行执行作业。作业可以是单个命令或必须针对输入中的每一行运行的小脚本。典型的输入是文件列表、主机列表、用户列表、URL 列表或表列表。作业也可以是从管道读取的命令。然后,GNU并行可以将输入分成块,并将块并行地输送到每个命令中。
如果您今天使用 xargs 和 tee,您会发现 GNU 并行非常易于使用,因为 GNU 并行被编写为具有与 xargs 相同的选项。如果你在shell中编写循环,你会发现GNU并行可能能够取代大部分循环,并通过并行运行多个作业使它们运行得更快。
GNU 并行确保命令的输出与顺序运行命令时得到的输出相同。这使得可以使用 GNU 并行的输出作为其他程序的输入。
答案3
find
不会为你做那件事。
创建一个脚本,找到 for_loop.sh 脚本并执行它们,如下所示:
#!/bin/bash
for theScript in $(find dir_* -name for_loop.sh); do
"$theScript" &
done
如果脚本必须在子目录内运行,请尝试cd
进入之前,也许像cd $(dirname "$theScript") && . $(basename "$theScript")
.
我的例子没有经过详细测试并且不具有容错性......
编辑1:
作为佐藤桂注释正确,如果目录名称中有空格,上面的脚本就会中断。
所以我改为循环read
:
#!/bin/bash
find dir_* -name for_loop.sh | while IFS= read -r theScript; do
"$theScript" &
done
答案4
你可以从你的顶级目录做
for D in `find . -type d -maxdepth 1`
do
$D/<yourScriptName>.sh &
done
“&”是在后台运行它们