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

xargs: losing output when redirecting stdout to a file in parallel mode

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

以下 shell 命令演示了 minimum, complete, and verifiable example 的问题。我使用 xargs 生成 2550 个数字,将其分成每行 100 个参数,每行总共 26 行,其中第 26 行仅包含 50 个参数。

# 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中使用>>(create/append归档)时出现,问题似乎没有表现出来:

# 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

我知道这个问题是关于 xargs 的,但是如果您仍然遇到问题,那么 GNU Parallel 可能会有帮助。您的 xargs 调用将转换为:

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

您的问题是由于混合了不同进程的输出。此处显示:

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*

解决方案是缓冲每个作业的输出 - 在内存或 tmp 文件中(就像 GNU Parallel 所做的那样)。