Xargs:在并行模式下将标准输出重定向到文件时丢失输出



我在并行模式下使用GNU xargs(版本4.2.2),当重定向到一个文件时,我似乎可靠地失去了输出。当重定向到管道时,它似乎工作正常。

下面的shell命令演示了这个问题的一个最小的、完整的、可验证的示例。我使用xargs生成2550个数字,将其分成每行100个args,共计26行,其中第26行仅包含50个args。

# generate numbers 1 to 2550 where each number is on its own line
$ seq 1 2550 > /tmp/nums
$ wc -l /tmp/nums
2550 /tmp/nums
# piping to wc is accurate: 26 lines, 2550 args
$ xargs -P20 -n 100 </tmp/nums | wc
     26    2550   11643
# redirecting to a file is clearly inaccurate: 22 lines, 2150 args
$ xargs -P20 -n 100 </tmp/nums >/tmp/out; wc /tmp/out
     22  2150 10043 /tmp/out

我相信这个问题与底层shell无关,因为shell会在命令执行之前执行重定向,并等待xargs完成。在本例中,我假设xargs在刷新缓冲区之前就完成了。但是,如果我的假设是正确的,我不知道为什么在写入管道时不会出现此问题。

编辑:

在shell中使用>>(创建/追加到文件)时出现,问题似乎没有出现:

# appending to file
$ >/tmp/out
$ xargs -P20 -n 100 </tmp/nums >>/tmp/out; wc /tmp/out
     26    2550   11643
# creating and appending to file
$ rm /tmp/out
$ xargs -P20 -n 100 </tmp/nums >>/tmp/out; wc /tmp/out
     26    2550   11643

您的问题是由于不同进程的输出混合。如下所示:

parallel perl -e '$a="1{}"x10000000;print $a,"\n"' '>' {} ::: a b c d e f
ls -l a b c d e f
parallel -kP4 -n1 grep 1 > out.par ::: a b c d e f
echo a b c d e f | xargs -P4 -n1 grep 1 > out.xargs-unbuf
echo a b c d e f | xargs -P4 -n1 grep --line-buffered 1 > out.xargs-linebuf
echo a b c d e f | xargs -n1 grep 1 > out.xargs-serial
ls -l out*
md5sum out*

解决方案是缓冲每个作业的输出——要么在内存中,要么在tmpfiles中(就像GNU Parallel那样)。

我知道这个问题是关于xargs的,但是如果你一直对它有问题,那么也许GNU Parallel可能会有所帮助。您的xargs调用将转换为:

$ < /tmp/nums parallel -j20 -N100 echo > /tmp/out; wc /tmp/out
26  2550 11643 /tmp/out

最新更新