Есть ли способ увидеть прогресс tar в каждом файле?


122

У меня есть пара больших файлов, которые я хотел бы сжать. Я могу сделать это, например, с

tar cvfj big-files.tar.bz2 folder-with-big-files

Проблема в том, что я не вижу никакого прогресса, поэтому я понятия не имею, сколько времени это займет или что-то в этом роде. Используя, vя могу по крайней мере увидеть, когда каждый файл будет завершен, но когда файлов мало и они большие, это не самый полезный.

Есть ли способ получить tar, чтобы показать более детальный прогресс? Например, процент выполнения или индикатор выполнения или оставшееся время или что-то еще. Либо для каждого отдельного файла, либо для всех, либо для обоих.

Ответы:


100

Я предпочитаю oneliners, как это:

tar cf - /folder-with-big-files -P | pv -s $(du -sb /folder-with-big-files | awk '{print $1}') | gzip > big-files.tar.gz

Это будет иметь следующий результат:

4.69GB 0:04:50 [16.3MB/s] [==========================>        ] 78% ETA 0:01:21

Для OSX (из ответа Кендзи)

tar cf - /folder-with-big-files -P | pv -s $(($(du -sk /folder-with-big-files | awk '{print $1}') * 1024)) | gzip > big-files.tar.gz

2
В OSX du не принимает аргумент -b, необходимый для возврата к: $ ((du -sk / folder-with | awk '{print $ 1}') * 1024))
выпуск

4
Хорошо, один лайнер. Вы можете это объяснить? Или это просто волшебно работает как-то?
Киссаки

2
Хорошо, у меня это естьpv $FILE.tgz | tar xzf - -C $DEST_DIR
Кшиштоф Шевчик

1
Для OS X мне нужно было использовать форму квадратной скобки для арифметического расширения, которое делало: tar cf - /folder-with-big-files -P | pv -s $[$(du -sk /folder-with-big-files | awk '{print $1}') * 1024] | gzip > big-files.tar.gzбез этого изменения я получал-bash: syntax error near unexpected token ')'
Дин Беккер

1
Обратите внимание, что прогресс не будет отображаться до тех пор, пока не завершится выполнение команды du, что может занять некоторое время в зависимости от размера, сложности и фрагментации каталога.
Rooster242

75

Вы можете использовать PV для достижения этой цели. Чтобы правильно сообщить о прогрессе, pvнужно знать, сколько байтов вы на него бросаете. Итак, первым шагом является вычисление размера (в килобайтах). Вы также можете полностью сбросить индикатор выполнения и просто pvсказать, сколько байтов он видел; это сообщило бы: «сделано так много и так быстро».

% SIZE=`du -sk folder-with-big-files | cut -f 1`

А потом:

% tar cvf - folder-with-big-files | pv -p -s ${SIZE}k | \ 
     bzip2 -c > big-files.tar.bz2

Здорово. pvпохоже, не поставляется с Mac OS X, но попробую это, как только у меня будет компьютер с MacPorts. Не могли бы вы объяснить, что вы там делаете? Не совсем уверен, что именно делает первая строка.
Свиш

4
первая строка: получить информацию о том, сколько байтов будет обработано. вторая строка: используйте размер из первой строки, чтобы позволить pv отображать 'progress'. так как вы передаете данные, pv не знает, сколько еще будет байтов.
Акира

Одно дополнение: SIZE=$(($SIZE * 1000 / 1024))- Я не знаю, является ли это причудой на моей конкретной платформе, поэтому я не добавляю ее в ответ: duвозвращает размер, где 1 КБ = 1024 байта, в то время как, pvкажется, ожидает 1 КБ = 1000 байт. (Я нахожусь на Ubuntu 10.04)
Изката

2
@lzkata вы всегда можете попросить duиспользовать предпочтительный размер блока, например du -s --block-size=1000, или просто работать с простыми байт, например , падение k«S от duи pvвызовов. Тем не менее, я ожидал бы, что оба будут использовать, 1024если не указано иное, например, --siвключение du, например.
Леголас

1
или просто отбросьте k-вещи и просто используйте простые байты ( du -sbи pv -sбез какого-либо модификатора). это должно положить конец всей путанице.
Акира

22

лучше прогресс бар ..

apt-get install pv dialog

(pv -n file.tgz | tar xzf - -C target_directory ) \
2>&1 | dialog --gauge "Extracting file..." 6 50

введите описание изображения здесь


2
Это работает для извлечения, но вам все равно нужно сделать одну из более сложных команд для создания (который был первоначальный вопрос). Это могло все еще быть объединено с теми; это просто сложнее.
Даниэль Х

17

Проверьте параметры --checkpointи --checkpoint-actionна странице информации о tar (что касается моего дистрибутива, описание этих параметров не содержится на странице руководства → RTFI).

См. Https://www.gnu.org/software/tar/manual/html_section/tar_26.html.

С их помощью (и, возможно, с функциональностью, чтобы написать свою собственную команду контрольной точки), вы можете рассчитать процент ...


3
Это должен быть правильный ответ. Другие просто объясняют дополнительные инструменты (не установленные по умолчанию, кроме того) для достижения чего-то подобного.
Кармин Гиангрегорио

@Sardathrion Может быть, потому что это tarспецифично для GNU .
17

11

Вдохновленный ответом помощника

Другой способ - использовать нативные tarопции

FROMSIZE=`du -sk ${FROMPATH} | cut -f 1`;
CHECKPOINT=`echo ${FROMSIZE}/50 | bc`;
echo "Estimated: [==================================================]";
echo -n "Progess:   [";
tar -c --record-size=1K --checkpoint="${CHECKPOINT}" --checkpoint-action="ttyout=>" -f - "${FROMPATH}" | bzip2 > "${TOFILE}";
echo "]"

результат как

Estimated: [==================================================]
Progess:   [>>>>>>>>>>>>>>>>>>>>>>>

полный пример здесь


4

Использование только смолы

tarимеет опцию (начиная с v1.12) для печати информации о состоянии сигналов --totals=$SIGNO, например:

tar --totals=USR1 -czf output.tar input.file
Total bytes written: 6005319680 (5.6GiB, 23MiB/s)

Total bytes written: [...]Информация печатается на каждом сигнале USR1, например:

pkill -SIGUSR1 tar

Источник:


3

Только что заметил комментарий о MacOS, и хотя я думаю, что решение от @akira (и pv) гораздо точнее, я подумал, что я поймал догадку и быстрый обходной путь в моей коробке MacOS с tar и отправил бы ему сигнал SIGINFO. Как ни странно, это сработало :), если вы работаете в BSD-подобной системе, это должно работать, но на Linux-боксе вам может потребоваться отправить SIGUSR1 и / или tarможет не работать так же.

Недостатком является то, что он предоставит вам только вывод (на стандартный вывод), показывающий, как далеко находится текущий файл, так как я предполагаю, что он понятия не имеет, насколько велик поток данных, который он получает.

Так что да, альтернативный подход - запускать tar и периодически отправлять SIGINFO каждый раз, когда вы хотите узнать, как далеко он продвинулся. Как это сделать?

Специальный ручной подход

Если вы хотите иметь возможность проверять статус на специальной основе, вы можете нажать control-T(как упомянул Брайан Свифт) в соответствующем окне, которое передаст сигнал SIGINFO. Я полагаю, что проблема в том, что он отправит его всей вашей цепочке, так что если вы делаете:

% tar cvf - folder-with-big-files | bzip2 -c > big-files.tar.bz2

Вы также увидите bzip2 отчет о его статусе вместе с tar:

a folder-with-big-files/big-file.imgload 0.79  cmd: bzip2 13325 running 
      14 0.27u 1.02s 

      adding folder-with-big-files/big-file.imgload (17760256 / 32311520)

Это хорошо работает, если вы просто хотите проверить, зависает ли tarваш бег, или просто медленно. В этом случае вам, вероятно, не нужно слишком беспокоиться о проблемах форматирования, так как это всего лишь быстрая проверка.

Этакий автоматизированный подход

Если вы знаете, что это займет некоторое время, но хотите что-то вроде индикатора прогресса, альтернативой может быть запуск вашего процесса tar, а в другом терминале определить его PID, а затем выбросить его в скрипт, который просто несколько раз посылает сигнал через , Например, если у вас есть следующий скриптлет (и вызовите его, как говорится script.sh PID-to-signal interval-to-signal-at):

#!/bin/sh

PID=$1
INTERVAL=$2
SIGNAL=29      # excuse the voodoo, bash gets the translation of SIGINFO, 
               # sh won't..

kill -0 $PID   # invoke a quick check to see if the PID is present AND that
               # you can access it..

echo "this process is $$, sending signal $SIGNAL to $PID every $INTERVAL s"
while [ $? -eq 0 ]; do
     sleep $INTERVAL;
     kill -$SIGNAL $PID;    # The kill signalling must be the last statement
                            # or else the $? conditional test won't work
done
echo "PID $PID no longer accessible, tar finished?"

Если вы вызываете его таким образом, поскольку вы нацеливаетесь только на него, tarвы получите более похожий результат

a folder-with-big-files/tinyfile.1
a folder-with-big-files/tinyfile.2
a folder-with-big-files/tinyfile.3
a folder-with-big-files/bigfile.1
adding folder-with-big-files/bigfile.1 (124612 / 94377241)
adding folder-with-big-files/bigfile.1 (723612 / 94377241)
...

что я признаю, это довольно мило.

И последнее, но не менее важное - мои скрипты довольно ржавые, поэтому, если кто-то захочет пойти и почистить / исправить / улучшить код, продолжайте свою жизнь :)


2
Если он работает tarв командной строке, при вводе команды control-Tбудет отправлено SIGINFO. Если бы это было в сценарии, это было бы сделано сkill -INFO pid
Брайан Свифт

Полностью забыл control-T, я явно привык спамить слишком много окон консоли для моего же блага ..
tanantish

1
почему я не вижу -SIGINFO, когда делаюkill -l
Фелипе Альварес

2

Вдохновленный ответом Ноа Спурриера

function tar {
  local bf so
  so=${*: -1}
  case $(file "$so" | awk '{print$2}') in
  XZ) bf=$(xz -lv "$so" |
    perl -MPOSIX -ane '$.==11 && print ceil $F[5]/50688') ;;
  gzip) bf=$(gzip -l "$so" |
    perl -MPOSIX -ane '$.==2 && print ceil $F[1]/50688') ;;
  directory) bf=$(find "$so" -type f | xargs du -B512 --apparent-size |
    perl -MPOSIX -ane '$bk += $F[0]+1; END {print ceil $bk/100}') ;;
  esac
  command tar "$@" --blocking-factor=$bf \
    --checkpoint-action='ttyout=%u%\r' --checkpoint=1
}

Источник


17
Небольшой контекст и объяснение может быть?
Киссаки

1

Если вы знаете номер файла вместо общего размера всех из них:

альтернатива (менее точная, но подходящая) заключается в использовании опции -l и отправке в канале unix имен файлов вместо содержимого данных.

Давайте поместим 12345 файлов в mydir , команда:

[myhost@myuser mydir]$ tar cfvz ~/mytarfile.tgz .|pv -s 12345 -l > /dev/null 

вы можете знать это значение заранее (из-за вашего варианта использования) или использовать какую-то команду, например find + wc, чтобы обнаружить его:

[myhost@myuser mydir]$ find | wc -l
12345

Итак, почему бы не поместить эту команду в подкоманду? =)
Кирби

tar cfvz ~/mytarfile.tgz . | pv -s $(find . | wc -l) -l > /dev/null, Работает ли это для вас?
Кирби

1

Метод, основанный на tqdm :

tar -v -xf tarfile.tar -C TARGET_DIR | tqdm --total $(tar -tvf tarfile.tar | wc -l) > /dev/null

1

В macOS сначала убедитесь, что у вас есть все доступные команды, и установите недостающие (например pv), используя brew .

Если вы хотите только tar без сжатия , используйте:

tar -c folder-with-big-files | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] > folder-with-big-files.tar

Если вы хотите сжать , перейдите с:

tar cf - folder-with-big-files -P | pv -s $[$(du -sk folder-with-big-files | awk '{print $1}') * 1024] | gzip > folder-with-big-files.tar.gz

Примечание. Может пройти некоторое время, прежде чем появится индикатор выполнения. Попробуйте сначала небольшую папку, чтобы убедиться, что она работает, а затем перейдите к папке с большими файлами.


0

Вот несколько номеров резервной копии Prometheus (метрических данных) на Debian / buster AMD64:

root# cd /path/to/prometheus/
root# tar -cf - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar )

Отменил это задание, так как на диске недостаточно свободного места.

Эксперименты с zstdкомпрессором для tarмониторинга прогресса с использованием pv:

root# apt-get update
root# apt-get install zstd pv

root# tar -c --zstd -f - ./metrics | ( pv -p --timer --rate --bytes > prometheus-metrics.tar.zst )
10.2GiB 0:11:50 [14.7MiB/s]

root# du -s -h prometheus
62G    prometheus

root# du -s -h prometheus-metrics.tar.zst
11G    prometheus-metrics.tar.zst
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.