xargs:tar:被信号13终止

时间:2019-04-29 15:39:40

标签: pipe tar xargs

我正在运行以下命令,以使用git来将文件从tar给出的列表复制到另一个目录。

git ls-files -z | xargs -0 tar -c | tar -x -C ~/tmp

这似乎在某些存储库上有效,但不适用于我的存储库:

xargs: tar: terminated by signal 13

1 个答案:

答案 0 :(得分:2)

回答我自己的问题 1

信号13的管道坏了:接收端停止读取,但是我们仍在管道中。

我的第一个提示是一个有问题的文件,所以我们将-t选项添加到xargs以便打印命令:

git ls-files -z | xargs -t -0 tar -c | tar -x -C ~/tmp

输出:

tar -c [long list of files (2994 files)]
tar -c [sightly less long list of files (~700 files)]

这时问题似乎很明显:我们将两个 tar调用传递到一个管道中,因此管道中断了(信号13)。

实际上,在阅读xargs手册后,我们可以看到:

  

将建立命令命令行,直到达到系统定义的限制(除非使用-n和-L选项)。 指定的命令将被调用多次,以用尽输入项列表。

您可以使用xargs来检查xargs --show-limits的限制。如果参数长度超过系统限制,则xargs会生成多个命令。

由于命令行的系统限制很高(至少在我的系统上是131072字节,与我的文件相当,〜3000个文件),这可以定义为一般情况。这意味着,如果文件列表适合系统定义的限制,则初始命令可以正常工作。

通过使用xargs选项限制-L将在每次调用中抛出的文件数量,我们可以针对每种情况(至少有2个文件)进行重现:

git ls-files -z | xargs -L 1 -t -0 tar -c | tar -x -C ~/tmp

解决方案实际上是通过使用tar的xargs选项完全删除-T,以从文件(或-,表示stdin)中读取文件列表:

git ls-files -z | tar --null -T - -c | tar -x -C ~/tmp

git ls-files | tar -T - -c | tar -x -C ~/tmp

1 https://discuss.circleci.com/t/local-checkout-fails-using-cli-tar-terminates-with-signal-13/28632/14