【发布时间】:2015-12-03 16:58:22
【问题描述】:
我在并行模式下使用 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中使用>>(创建/附加到文件)时出现,问题似乎没有表现出来:
# 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
【问题讨论】:
-
我在这两种情况下都得到了准确的输出。
Shell> wc -l /tmp/nums 2550 /tmp/nums Shell> xargs -P20 -n 100 </tmp/nums | wc 26 2550 11643 Shell> xargs -P20 -n 100 </tmp/nums >/tmp/out; wc /tmp/out 26 2550 11643 /tmp/out Shell> -
如果你清空输出文件然后使用
>>而不是>重定向,你能可靠地得到正确的结果吗?如果是这样,那就有某种解释。 -
@JonathanLeffler:看起来你是对的。使用
>>,问题不会出现。我尝试提前创建文件并使用“>”进行重定向(截断现有文件),但问题似乎再次出现。 -
当您使用
>重定向时,/tmp/out的开头会出现哪些数字?它们是像 1、2、3 这样的数字,还是像 2001、2002、2003 这样的数字?我在想出一个合理的机制来解决这个问题时遇到了一些问题。管道和附加行为很容易解释。但是>的行为应该基本相同,我想知道事情是如何被破坏的。你有truss或strace可用吗?如果是这样,看看xargs进程做了什么可能会很有启发意义(但不是——至少首先——它的子进程做了什么)。 [...继续...] -
[…continuation…] 运行
strace -o xargs.log xargs -P 20 -n 100 </tmp/nums > /tmp/out后,xargs.log中是否有任何有用的信息?我正在考虑文件描述符 1 上的lseek()之类的东西,但我不确定这是否合理。一个问题可能是实际上是孩子造成了恶作剧。在这种情况下,您需要使用“关注孩子”选项 (-f) 来查看导致问题的原因。但输出量会更大。我在 Mac OS X 10.10.5 和 Ubuntu 14.04 LTS(在 Mac OS X 下的 VM 中运行)都得到了“正确”的输出。