Отвечая на мой вопрос 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 файлов), это можно определить как общий случай. Это означает, что если список файлов соответствует системному пределу, начальная команда работает хорошо.
Мы можем воспроизвести для каждого случая (ну, по крайней мере, с 2 файлами), ограничив количество файлов, которые xargs
будет выдавать при каждом вызове с опцией -L
:
git ls-files -z | xargs -L 1 -t -0 tar -c | tar -x -C ~/tmp
На самом деле решение состоит в том, чтобы вообще удалить xargs
, используя опцию tar -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