我可以同时运行3个命令,例如:
mongodump -h staging .... & mongodump -h production .... & mongodump -h web ... &
当一个mongodump完成后,我想启动另一个mongodump。
由于服务器将耗尽CPU,因此无法同时运行所有26个mongodumps命令。最多同时运行3个mongodumps。
xarg
的-P
选项来并行运行指定数量的调用:
请注意,-P
选项不是POSIX强制要求的, 但GNU的xargs
和BSD/macOS的xargs
都支持它。
xargs -P 3 -n 1 mongodump -h <<<'staging production web more stuff and so on'
mongodump -h staging
、mongodump -h production
和 mongodump -h web
,等待所有三个调用完成后,继续执行 mongodump -h more
、mongodump -h stuff
和 mongodump -h and
等等。
-n 1
从输入流中获取一个参数,并调用 mongodump
;如有需要,可以单引号或双引号括起输入中的参数。xargs
支持 -P 0
,其中 0
表示“尽可能同时运行多个进程”。-I {}
来指示,并定义 {}
作为每个输入行的占位符。xargs -P 3 -I {} mongodump -h {} after <<<$'staging\nproduction\nweb\nmore\nstuff'
现在,每个输入参数都会被替换为{}
,允许参数after
在其后出现。
但是,请注意,每个输入行都不可避免地作为一个单一的参数传递。
BSD/macOS的xargs
允许您将-n
与-J {}
结合使用,而无需提供基于行的输入,但GNU的xargs
不支持-J
。
简而言之:只有BSD/macOS允许您将输入参数的放置与一次读取多个参数相结合。
请注意,xargs
不会并行序列化命令的标准输出,因此并行进程的输出可以交错到达。
使用GNUparallel
可以避免这个问题 - 请参见下文。
parallel
xargs
的优点在于它是一个标准实用程序,因此在支持-P
的平台上,没有任何先决条件。parallel
(一个二进制文件)来自moreutils
软件包-请参见其主页。
GNU parallel
(一个Perl脚本)-更加强大-来自parallel
软件包感谢,twalberg. -请参见其主页。
parallel
工具,那么使用 parallel --version
命令可以告诉您它是哪一个(GNU parallel
会显示版本号和版权信息,而 "moreutils" 的 parallel
则会提示无效选项并显示语法摘要)。
parallel
工具:parallel -j 3 -n 1 mongodump -h -- staging production web more stuff and so on
# Using -i to control placement of the argument, via {}
# Only *1* argument at at time supported in that case.
parallel -j 3 -i mongodump -h {} after -- staging production web more stuff and so on
xargs
不同,此parallel
实现不会从stdin获取要传递的参数;所有要传递的参数都必须在命令行中通过--
后面传递。parallel
实现提供的唯一功能超出了xargs
可以做到的是:
-l
选项允许推迟进一步的调用,直到系统负载超过指定阈值以下。man
页):"stdout和stderr通过相应的内部管道串行化,以防止烦人的并发输出行为。",但我发现在其man
页日期为2009-07-2的版本中并非如此 - 见最后一节。parallel
:
向Ole Tange致敬。
parallel -P 3 -n 1 mongodump -h <<<$'staging\nproduction\nweb\nmore\nstuff\nand\nso\non'
# Alternative, using ::: followed by the target-command arguments.
parallel -P 3 -n 1 mongodump -h ::: staging production web more stuff and so on
# Using -n 1 and {} to control placement of the argument.
# Note that using -N rather than -n would allow per-argument placement control
# with {1}, {2}, ...
parallel -P 3 -n 1 mongodump -h {} after <<<$'staging\nproduction\nweb\nmore\nstuff\nand'
parallel
旨在成为xargs
的更好的继承者,提供了许多更多的功能:一个值得注意的例子是能够 对传递的参数执行复杂的转换,可选地基于Perl的正则表达式;另请参见:man parallel
和man parallel_tutorial
。
以下命令测试了xargs
和两个parallel
实现如何处理并行运行的命令交错输出的方式——它们是按照到达顺序显示输出,还是尝试对其进行序列化:
有2个级别的序列化,都会引入开销:
行级序列化:防止来自不同进程的部分行混合在单个输出行中。
进程级序列化:确保给定进程的所有输出行被分组在一起。
这是最用户友好的方法,但请注意,这意味着只有第一个创建输出的命令终止后,您才会开始以序列方式看到其他命令的输出。
据我所知,只有GNU的parallel
提供了任何序列化(尽管“moreutils” parallel
手册日期为2009年7月2日的页面[1]上说过),而且它支持两种方法。
./tst
,其内容如下:#!/usr/bin/env bash
printf "$$: [1/2] entering with arg(s): $*"
sleep $(( $RANDOM / 16384 ))
printf " $$: [2/2] finished entering\n"
echo " $$: stderr line" >&2
echo "$$: stdout line"
sleep $(( $RANDOM / 8192 ))
echo " $$: exiting"
不会进行串行化:单个输出行可以包含来自多个进程的输出。
$ xargs -P 3 -n 1 ./tst <<<'one two three'
2593: [1/2] entering with arg(s): one2594: [1/2] entering with arg(s): two 2593: [2/2] finished entering
2593: stderr line
2593: stdout line
2596: [1/2] entering with arg(s): three 2593: exiting
2594: [2/2] finished entering
2594: stderr line
2594: stdout line
2596: [2/2] finished entering
2596: stderr line
2596: stdout line
2594: exiting
2596: exiting
$ parallel -j 3 ./tst -- one two three
3940: [1/2] entering with arg(s): one3941: [1/2] entering with arg(s): two3942: [1/2] entering with arg(s): three 3941: [2/2] finished entering
3941: stderr line
3941: stdout line
3942: [2/2] finished entering
3942: stderr line
3942: stdout line
3940: [2/2] finished entering
3940: stderr line
3940: stdout line
3941: exiting
3942: exiting
GNU parallel
(版本20170122)
默认情况下,进程级别的串行化(分组)会发生。
使用--line-buffer
(在更新版本中为--lb
)选择行级别的串行化,或使用-u
(--ungroup
)退出任何类型的串行化。
请注意,在每个组中,标准错误输出出现在标准输出之后(而版本20170122附带的手册声称标准错误输出首先出现)。
$ parallel -P 3 ./tst ::: one two three
2544: [1/2] entering with arg(s): one 2544: [2/2] finished entering
2544: stdout line
2544: exiting
2544: stderr line
2549: [1/2] entering with arg(s): three 2549: [2/2] finished entering
2549: stdout line
2549: exiting
2549: stderr line
2546: [1/2] entering with arg(s): two 2546: [2/2] finished entering
2546: stdout line
2546: exiting
2546: stderr line
&
(或者如果所有内容在一行上,则使用;
),那么它将不会并行执行整个过程。echo "Hello" & sleep 1 ;
echo "Hello Again" & sleep 1 ;
echo "Once More" & sleep 1 ;
wait
命令来确保它们已经完成。 - mklement0
&
替换为;
吗? - Jack