我目前拥有当前的脚本。
#!/bin/bash
# script.sh
for i in {0..99}; do
script-to-run.sh input/ output/ $i
done
我希望使用xargs并行运行它。我已经尝试过
script.sh | xargs -P8
但是以上操作一次只执行一次。尝试使用-n8也不行。 在要执行的脚本循环行末尾添加&会尝试一次性运行99次脚本。如何才能每次仅运行8个循环,总共达到100次。
我目前拥有当前的脚本。
#!/bin/bash
# script.sh
for i in {0..99}; do
script-to-run.sh input/ output/ $i
done
我希望使用xargs并行运行它。我已经尝试过
script.sh | xargs -P8
但是以上操作一次只执行一次。尝试使用-n8也不行。 在要执行的脚本循环行末尾添加&会尝试一次性运行99次脚本。如何才能每次仅运行8个循环,总共达到100次。
来自xargs
手册页:
本手册页记录了GNU版本的xargs。 xargs从标准输入读取项目,这些项目由空格(可以用双引号、单引号或反斜杠保护)或换行符分隔,并执行该命令(默认为/bin/echo)一次或多次,后跟任何初始参数,接着是从标准输入读取的项目。标准输入上的空行将被忽略。
这意味着对于您的示例,xargs
正在等待和收集脚本的所有输出,然后运行echo <that output>
。不是非常有用,也不是您想要的。
-n
参数表示每个运行的命令使用输入中的多少项(仅仅是关于并行性方面的内容)。
要使用xargs
实现您想要的功能,您需要执行类似以下未经测试的操作:
printf %s\\n {0..99} | xargs -n 1 -P 8 script-to-run.sh input/ output/
以下是该过程的简要说明。
printf %s\\n {0..99}
- 按行打印从 0
到 99
的数字。xargs
echo {0..99} |
同样可以正常工作。然而, <<<{0..99}
似乎无法正常工作;尽管 <<<word
被文档描述为花括号展开单词,但这在我手头可用的任何 bash 版本中都不起作用。 - rici<<
不会发生,但对于 <<<
会发生,所以 *耸肩*
)。在这里文档和字符串中发生和不发生的扩展有点奇怪。 - Etan Reisnertime head -12 <(yes "1") | xargs -n1 -P4 sleep
,会执行12个sleep 1
命令,并发地执行4个。该命令将花费3秒钟的时间。 - Walter A-P 0
会利用系统上的CPU数量。 - slfseq 0 99
来获得数字序列(使用换行符分隔;至少在Linux上有效)。 - jena使用 GNU Parallel,您可以执行以下操作:
parallel script-to-run.sh input/ output/ {} ::: {0..99}
如果您不想每个CPU核心运行一个作业,请添加-P8
。
与相反的xargs
相比,即使输入包含空格、'或"(但此处不是这种情况),它也会做正确的事情。它还确保来自不同作业的输出不会混合在一起,因此,如果您使用输出,则保证不会从两个不同的作业中获得半行。
GNU Parallel是一个通用的并行程序,可以轻松地在同一台计算机或具有ssh访问权限的多台计算机上并行运行作业。
如果您有32个不同的作业要在4个CPU上运行,一种简单的并行化方法是在每个CPU上运行8个作业:
相反,GNU Parallel在一个进程完成时生成一个新进程-保持CPU活动状态,从而节省时间:
安装
如果您的发行版没有打包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
这里是一个与 find
一起并行运行命令的示例:
find -name "*.wav" -print0 | xargs -0 -t -I % -P $(nproc) flac %
-print0
会用空字节代替换行符来终止文件名,因此我们可以在 xargs 中使用 -0
来防止将文件名中的空格视为两个不同的参数。
-t
表示详细模式,使得 xargs 打印出每个要执行的命令,如果需要的话可以保留,否则请删除。
-I %
表示将命令中的 %
替换为从标准输入读取到的参数。
-P $(nproc)
表示最大并发运行 nproc
个命令实例(nproc
可以打印出可用处理器数量)。
flac %
是我们要执行的命令,之前的 -I %
表示它会变成 flac foo.wav
。
另请参阅:xargs(1)手册
bash -c
。例如,如果您想要删除原始文件,则可以执行 bash -c "flac \"%\" && rm \"%\""
。 - Peter Frost--verbose
而不是-t
以及--max-procs =
而不是-P
,那么理解起来会更容易一些。 - bfontaineseq 1 500 | xargs -n 1 -P 8 script-to-run.sh input/ output/