使用xargs并行运行程序


85

我目前有当前脚本。

#!/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次。


那是我最初想要做的,但是由于我在Windows上,所以不得不求助于xargs。我无法在Windows上运行GNU Parallel
Olivier 2015年

是该脚本自称还是您在此处询问时只是混淆了名称?
Etan Reisner

抱歉,它应该调用另一个脚本。我会修复它
Olivier 2015年

Answers:


128

xargs手册页:

本手册页记录了xargs的GNU版本。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
    • 最多每次运行命令行一个参数
    • 一次最多运行八个进程

7
实际上,您不需要将参数放在单独的行上;xargs分词。所以echo {0..99} |也一样。<<<{0..99}似乎不起作用;尽管<<<word被记录为大括号扩展词,但我使用的任何版本的bash都没有这样做。
rici 2015年

1
@rici当时看起来像是一个文档错误,特别是因为Here Documents的文档没有提到大括号扩展(并且在快速测试中也没有发生),尽管他们也没有提到波浪号扩展(这没有发生)对于,<<但确实<<<如此*shrug*)。在我看来,在这里的文档和这里的字符串中进行和不进行的扩展都有些奇怪。
伊坦·赖斯纳

1
您如何使用换行符(例如,换行符)将结果与不同运行分开?
nirvana-msu

3
演示:time head -12 <(yes "1") | xargs -n1 -P4 sleep将运行12个sleep 1命令,并行4个。该命令将花费3秒钟。
沃尔特A

66

使用GNU Parallel,您可以:

parallel script-to-run.sh input/ output/ {} ::: {0..99}

在添加-P8如果你希望运行每个CPU核心一个作业。

相反xargs,即使输入包含空格“或”(此处不是这种情况),它也会执行“正确的事情”。它还可以确保不同作业的输出不会混合在一起,因此,如果使用输出,您将确保您不会从两项不同的工作中获得半薪。

GNU Parallel是一个通用的并行器,使您可以轻松地在具有ssh访问权限的同一台计算机或多台计算机上并行运行作业。

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

简单的调度

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

GNU并行调度

安装

如果未打包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 67bd7bc7dc20aff99eb8f1266574dadb
12345678 67bd7bc7 dc20aff9 9eb8f126 6574dadb
$ md5sum install.sh | grep b7a15cdbb07fb6e11b0338577bc1780f
b7a15cdb b07fb6e1 1b033857 7bc1780f
$ sha512sum install.sh | grep 186000b62b66969d7506ca4f885e0c80e02a22444
6f25960b d4b90cf6 ba5b76de c1acdf39 f3d24249 72930394 a4164351 93a7668d
21ff9839 6f920be5 186000b6 2b66969d 7506ca4f 885e0c80 e02a2244 40e8a43f
$ 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


19
这没有回答问题,也没有指出为什么xargs无法实现同一目标。
张实唯2016年

8
之所以投票,是因为xarg对我而言确实与第二张图片所示的一样。
noonex

3
@noonex您是否知道不是每个人都使用所使用的xargs版本,并且-P并非在所有xargs版本中?
Ole Tange'2

19
也许并非所有人都知道,这个答案是由GNU parallel的作者提供的。
izkeros

1
拒绝投票的原因是,由于交互式提示弄乱了大多数脚本,导致软件未按首次尝试所述正确运行而出现明显的广告。
Daniel Sorichetti
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.