我正在尝试在bash脚本中的26台服务器上运行多个mongodump。
我可以运行3个命令,如
mongodump -h staging .... &
mongodump -h production .... &
mongodump -h web ... &
同时,当一个人完成时我想开始另一个mongodump。
我无法同时运行所有26个mongodumps命令,服务器将在CPU上运行。同时最多3个mongodumps。
答案 0 :(得分:5)
您可以使用 xarg
-P
选项来并行运行可指定数量的调用:
请注意-P
选项为not mandated by 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
,等待所有3次调用完成,然后继续mongodump -h more
,mongodump -h stuff
, mongodump -h and
,等等。
-n 1
从输入流中获取单个参数并调用mongodump
;如有必要,根据需要调整输入中的单引号或双引号。
注意: GNU xargs
- 但不是BSD xargs
- 支持-P 0
,其中0
表示:&#34;尽可能多地运行尽可能同时处理。&#34;
默认情况下,通过stdin提供的参数追加到指定的命令 如果您需要控制 where ,则在结果命令中放置相应的参数,
-I {}
表示,并将{}
定义为每个输入行的占位符。xargs -P 3 -I {} mongodump -h {} after <<<$'staging\nproduction\nweb\nmore\nstuff'
现在每个输入参数都替换为{}
,允许参数after
到来。
但请注意,每个输入行总是作为单个参数传递。
BSD / macOS xargs
允许您将-n
与-J {}
结合使用,而无需提供基于行的输入,但GNU xargs
没有&#39} ; t支持-J
简而言之:只有BSD / macOS允许您将输入参数的放置与一次读取多个参数结合起来。
请注意,xargs
并行不序列化stdout输出,以便并行进程的输出 interleaved 。
使用 GNU parallel
来避免此问题 - 请参阅下文。
parallel
xargs
具有成为标准实用程序的优势,因此在支持-P
的平台上,没有先决条件。
在Linux世界中(虽然也通过Homebrew在macOS上),有两个专门用于并行运行命令的实用程序,不幸的是,它们共享相同的名称; 通常,您必须按需安装:
parallel
包的 moreutils
(二进制) - 请参阅its home page。
- 更强大 - 来自parallel
包的GNU parallel
(Perl脚本)谢谢,twalberg。 - 请参阅{{ 3}}
如果您已有parallel
实用程序,parallel --version
将告诉您它是哪一个(GNU parallel
报告版本号和版权信息,&#34; moreutils&#34; 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
页面):&#34; stdout和stderr通过相应的内部管道进行序列化,以防止令人讨厌的并发输出行为。&#34;尽管我&#39;我们在man
页面的日期为2009-07-2的版本中发现了 not 的情况 - 请参阅上一节。parallel
:向its home page寻求帮助的提示。
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'
与xargs
一样,传递参数是通过 stdin 提供的,但GNU parallel
也支持在可配置的分隔符之后将它们放在命令行上(默认为:::
)。
与xargs
不同,每个输入行都被视为一个参数。
警告:如果您的命令涉及引用字符串,则必须使用-q
将它们作为不同的参数传递;例如,parallel -q sh -c 'echo hi, $0' ::: there
仅适用于-q
。
与 GNU xargs
一样,您可以使用-P 0
一次运行尽可能多的调用 ,充分利用机器人的能力,意味着,根据Ole,&#34;直到GNU Parallel遇到限制(文件句柄和进程)&#34;。
-P
并不像其他公用事业那样一次只运行一个进程,而是运行一个进程每CPU核心。默认情况下,并行执行的命令输出会按进程自动序列化(分组),以避免交错输出。
--line-buffer
(--lb
在更新的版本中)选择退出此行为或-u
(--ungroup
)允许甚至单个输出行混合来自不同进程的输出;有关详细信息,请参阅手册。 GNU parallel
,旨在成为xargs
的更好继承者,提供了更多功能:一个值得注意的例子是能够Ole Tange,可选择基于Perl 正则表达式;另请参阅:man parallel
和man parallel_tutorial
。
以下命令测试xargs
和两个parallel
实现如何处理并行运行的命令的交错输出 - 无论它们是在到达时显示输出还是尝试序列化它:
2级序列化,两者都引入了开销:
行级序列化:防止来自不同进程的部分行在单个输出行上混合。
流程级序列化:确保将给定流程的所有输出行组合在一起 这是用户最友好的方法,但请注意,这意味着您只能开始看到其他命令&#39;输出(按顺序)一旦创建输出的第一个终止。
据我所知,只有GNU parallel
提供任何序列化(尽管&#34; moreutils&#34; parallel
2009-07-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
(在Ubuntu 16.04和macOS 10.12上都有GNU和BSD / macOS实现):
不会发生序列化:单个输出行可以包含多个进程的输出。
$ 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
<强>&#34; moreutils&#34; parallel
(man
页面日期为2009-07-02的版本)
不会发生序列化:单个输出行可以包含多个进程的输出。
$ 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
)。
请注意,在每个组中,stderr输出在标准输出后输出(而版本20170122附带的手册页声称stderr输出首先)。
$ 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
[1]&#34; stdout和stderr通过相应的内部管道进行序列化,以防止烦人的并发输出行为。&#34;
请告诉我,我是否遗漏了某些东西。
答案 1 :(得分:1)
如果您只是排除每隔3 &
(如果它只在一行上使用;
),那么它就不会并行执行整个事情。
例如:
echo "Hello" & sleep 1 ;
echo "Hello Again" & sleep 1 ;
echo "Once More" & sleep 1 ;