我正在运行以下命令,以使用git
来将文件从tar
给出的列表复制到另一个目录。
git ls-files -z | xargs -0 tar -c | tar -x -C ~/tmp
这似乎在某些存储库上有效,但不适用于我的存储库:
xargs: tar: terminated by signal 13
答案 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