Как перенаправить стандартный вывод xz при выполнении команды tar | XZ?
Мне нужно использовать компрессор, такой как xz, для сжатия огромных архивов tar.
Я полностью осведомлен о предыдущих вопросах, таких как создание tar.xz в одной команде и использование многоядерности для сжатия / распаковки tar + gzip / bzip
Из них я обнаружил, что эта командная строка в основном работает:
tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz
Я использую решение для канала, потому что я абсолютно обязан передавать параметры в xz. В частности, xz очень сильно загружает процессор, поэтому я должен использовать -T0, чтобы использовать все доступные ядра. Вот почему я не использую другие возможности, такие как tar --use-compress-program или -J.
К сожалению, я действительно хочу записать все выходные данные tar и xz (т.е. неархивированные выходные данные) в файл журнала. В приведенном выше примере выход из системы всегда генерируется -v
опции.
С командной строкой выше, тот вывод журнала теперь напечатан на моем терминале.
Итак, проблема в том, что когда вы используете каналы для соединения tar и xz, как указано выше, вы не можете завершить командную строку чем-то вроде
>Log_File 2>&1
из-за этого раньше
> OUTPUT_FILE.tar.xz
Есть ли решение?
Я попытался завернуть в подоболочку, как это
(tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz) >Log_File 2>&1
но это не сработало.
2 ответа
Нормальный стандартный вывод tar
это тарбол и обычный вывод xz
это сжатый файл Ни одна из этих вещей не является журналами, которые вы должны записывать. Все журналы, кроме самих выходных файлов, записываются исключительно в stderr для обоих процессов.
Следовательно, вам нужно только перенаправить stderr, и вы не должны перенаправлять stdout, если только вы не хотите, чтобы ваш выходной файл смешивался с журналированием.
{ tar -cvf - paths_to_archive | xz -1 -T0 -v > OUTPUT_FILE.tar.xz; } 2>Log_File
Кстати - если вам интересно, почему xz -v
печатает больше контента, когда его вывод идет в TTY, ответ в этой строке message.c
: progress_automatic
флаг (говорящий xz, чтобы установить таймер для запуска SIGALRM
- который он рассматривает как признак того, что статус должен быть напечатан - каждую секунду) устанавливается только тогда, когда isatty(STDERR_FILENO)
правда. Таким образом, после того, как stderr был перенаправлен в файл, xz
больше не печатает этот вывод вообще; проблема не в том, что он неправильно перенаправлен, а в том, что он больше не существует.
Вы можете, однако, отправить SIGALRM
в xz
каждую секунду из вашего собственного кода, если вы действительно так склонны:
{
xz -1 -T0 -v > OUTPUT_FILE.tar.xz < <(tar -cvf - paths_to_archive) & xz_pid=$!
while sleep 1; do
kill -ALRM "$xz_pid" || break
done
wait "$xz_pid"
} 2>Log_File
(Код, который позволяет избежать округления времени, необходимого для xz
выполнить до ближайшей секунды возможно, но оставлено как упражнение для читателя).
Первый -cvf -
можно заменить на cv
,
Но нормальный стандартный вывод tar cvf -
это файл tar, который передается в xz
, Не уверен, что я полностью понимаю, может быть, это:
tar cv paths | xz -1 -T0 > OUTPUT.tar.xz 2> LOG.stderr
или же
tar cv paths 2> LOG.stderr | xz -1 -T0 > OUTPUT.tar.xz
или же
tar cv paths 2> LOG.tar.stderr | xz -1 -T0 > OUTPUT.tar.xz 2> LOG.xz.stderr
Не уверен если -T0
Реализовано, какую версию xz вы используете? (Может быть, https://github.com/vasi/pixz стоит посмотреть поближе) pv
программа, установленная с sudo apt-get install pv
в некоторых системах лучше показать прогресс для труб, чем xz -v
, Он скажет вам прогресс в процентах с ETA:
size=$(du -bc path1 path2 | tail -1 | awk '{print$1}')
tar c paths 2> LOG.stderr | pv -s$size | xz -1 -T0 > OUTPUT.tar.xz