如何阻止xargs严重合并多个进程的输出?


17

我正在使用xargs该选项--max-args=0(或者-P 0)。

但是,这些过程的输出将合并到stdout流中,而无需考虑适当的行分隔。因此,我经常会出现以下行:

<start-of-line-1><line-2><end-of-line-1>

当我在整个输出的模式中使用egrepwith时^xargs这弄乱了我的结果。

是否有某种方法可以强制xargs按顺序写进程输出(只要一个进程的输出是连续的,任何顺序都可以)?

还是其他解决方案?

编辑:有关用例的更多详细信息:

我想从不同的主机下载并解析网页。由于每个页面需要大约一秒钟的加载时间,因此我要并行处理几十个页面。

我的命令具有以下形式:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
wget -q -O- http://{}/somepage.html | egrep --count '^string'

我使用bash而不是Perl之类的东西,因为主机IP($ IPs变量)和其他一些数据来自包含的bash文件。


您能否为您的问题提供更完整的示例?目前尚不清楚您目前使用的方式或原因xargs
卡莱布

解决此问题的方法将很困难,需要为每个进程的stdout使用不同的文件描述符,并使用小型服务器来收集行。xargs似乎没有提供这种功能。
斯蒂芬·吉梅内斯

@Caleb到那里去,希望对您有所帮助:-)
Christoph Wurm

绝对不是轻量级的解决方案,但也许您可以使用make的jobs功能,我认为可以make正确合并输出行。
斯特凡希门尼斯

确实添加了--line-buffered标记来提供egrep帮助
iruvar

Answers:


6

这应该可以解决问题:

echo -n $IPs | xargs --max-args=1 -I {} --delimiter ' ' --max-procs=0 \
  sh -c "wget -q -O- 'http://{}/somepage.html' | egrep --count '^string'" | \
  { NUM=0; while read i; do NUM=$(($NUM + $i)); done; echo $NUM; }

这里的想法是进行单独的计数,最后将它们相加。如果单独的计数足够大而无法混合,则可能会失败,但事实并非如此。


14

GNU Parallel专为解决此问题而设计:

echo -n $IPs | parallel -d ' ' -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

如果您的IP位于文件中,它甚至更漂亮:

cat IPs | parallel -j0 wget -q -O- http://{}/somepage.html | egrep --count '^string'

要了解更多信息,请观看介绍性视频:http : //www.youtube.com/watch?v=OpaiGYxkSuQ


2
不错的工具!另外,我敢打赌,有人很快就会告诉你猫没有用。
斯蒂芬·吉梅内斯

1
我知道。但是我发现它更容易阅读,而且我通常在48核机器上工作,因此,空闲核之一的几个额外时钟周期仍然不是问题。
Ole Tange

如果它在Debian仓库中,则parallel对于该工作而言是完美的。
Christoph Wurm

1
@Legate Debian包含parallel来自moreutils的命令,这在这里就足够了:parallel -j99 -i sh -c 'wget -q -O- http://{}/somepage.html | egrep -c "^string"' -- $IPs
别再作恶了'

@Legate结账build.opensuse.org/package/...为一个.deb文件,并bugs.debian.org/cgi-bin/bugreport.cgi?bug=518696的错误来推动。
Ole Tange'8
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.