Показ общего прогресса в rsync: возможно ли это?

Вопрос или проблема

Я уже искал эту опцию, но нашёл только решения, которые включают в себя кастомные патчи. То, что это не отображается в –help и не получается найти больше информации, вероятно, указывает на то, что ответ ‘нет’, но я хотел бы получить подтверждение этого.

Можно ли показать общий прогресс передачи файлов с помощью rsync?

Теперь есть официальный способ сделать это в rsync (версии 3.1.0, протокол версии 31, протестировано на Ubuntu Trusty 14.04).

#> ./rsync -a --info=progress2 /usr .
    305,002,533  80%   65.69MB/s    0:00:01  xfr#1653, ir-chk=1593/3594)

Я пробовал с своей /usr папкой, потому что хотел эту функцию для передачи целых файловых систем, и /usr казался хорошим представительным образцом.

--info=progress2 показывает хороший общий процент, даже если это лишь частичное значение. На самом деле, моя папка /usr весит больше 6 гигабайт:

#> du -sh /usr
6,6G    /usr/

И rsync потратил много времени на сканирование всего этого. Поэтому почти всё время процент, который я видел, был около 90% завершения, но тем не менее, приятно видеть, что что-то копируется 🙂

Ссылки:

Следующее относится к версиям rsync 3.0.0 и выше. Описанные ниже параметры были введены в этой версии 1 марта 2008 года.

Вместе с –info=progress2 вы также можете использовать –no-inc-recursive (или её короткий –no-i-r вариант), чтобы отключить инкрементальную рекурсию.

Это создаст весь список файлов в начале, а не будет инкрементально обнаруживать больше файлов по мере передачи. Поскольку он будет знать все файлы перед началом, он даст лучший отчет о общем прогрессе. Это применимо к количеству файлов — оно не сообщает о прогрессе, основанном на размерах файлов.

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

Следующее взято из руководства rsync (источник – http://rsync.samba.org/ftp/rsync/rsync.html):

-r, –recursive

Это указывает rsync копировать директории рекурсивно. Смотрите также –dirs (-d). Начиная с rsync 3.0.0, используемый рекурсивный алгоритм теперь представляет собой инкрементальное сканирование, которое использует гораздо меньше памяти, чем раньше, и начинает передачу после завершения сканирования первых нескольких директорий. Это инкрементальное сканирование затрагивает только наш рекурсивный алгоритм и не изменяет нерекурсивную передачу. Это также возможно только тогда, когда обе стороны передачи имеют версию не ниже 3.0.0.

Некоторые опции требуют, чтобы rsync знал полный список файлов, поэтому эти опции отключают режим инкрементальной рекурсии. К ним относятся: –delete-before, –delete-after, –prune-empty-dirs и –delay-updates. Из-за этого стандартный режим удаления, когда вы указываете –delete, теперь –delete-during, когда обе стороны соединения имеют хотя бы 3.0.0 (используйте –del или –delete-during, чтобы явно запросить этот улучшенный режим удаления). Смотрите также опцию –delete-delay, которая является лучшим выбором, чем использование –delete-after.

Инкрементальную рекурсию можно отключить, используя опцию –no-inc-recursive или её короткий –no-i-r вариант.

Смотрите также https://rsync.samba.org для конкретных различий версий (прокрутите вниз и посмотрите ссылки на Release News).

Вы можете использовать ‘pv’ (apt-get install pv с Debian и Ubuntu). Я рекомендую отслеживать количество переданных файлов, так как объем передаваемых данных не связан с размером файлов, а зависит от разницы между источником и приемником. Подсчет файлов будет одинаково отслеживать прогресс как для одного большого дельта, так и для другого с маленьким дельта. Это означает, что в любом случае оценка ETA может быть далеко от истинного значения. Оценка на основе размера работает только если ваш приемник пуст, в этом случае дельта == размер источника.

Общая идея состоит в том, чтобы выводить одну строку на файл ‘переносимый’ от rsync и подсчитывать эти строки с помощью ‘pv’:

rsync -ai /source remote:/dest | pv -les [количество файлов] >/dev/null

Я обычно делаю резервные копии целых файловых систем (по нескольким причинам), в этом случае вы можете использовать гораздо более дешевый df для получения количества файлов (вместо du или find, которые будут обходить вашу иерархию источника еще раз после rsync). Опция -x, похоже, обеспечивает выполнение rsync на одной и той же файловой системе источника (и не следует за другими внутренними монтированиями):

rsync -aix /source remote:/dest | pv -les $(df -i /source | perl -ane 'print $F[2] if $F[5] =~ m:^/:') >/dev/null

Если вы хотите подсчитать файлы в /source в общем порядке, используйте find /source|wc -l (предупреждение: это может быть медленно и тяжело для I/O).

danakim прав. Нет тривиальных способов добавить индикатор общего прогресса.

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

Иными словами, самый простой способ рассчитать, сколько работы нужно сделать, — это на самом деле это сделать.

Для длительных передач я рад запустить du -s с обеих сторон. Даже watch -n1 du -s, если я чувствую себя действительно тревожным.

watch выполняет команду (du -s здесь) периодически (каждую 1 секунду) и отображает результат на весь экран.

Почти нет. Вы можете показывать только прогресс по файлам с помощью флага –progress, но это почти всё.

Я предполагаю, что вы можете написать обертку вокруг него или использовать любой из патчей, которые вы уже нашли, но вам стоит спросить себя, действительно ли это того стоит, действительно ли вам нужен общий прогресс для rsync?

Я также искал, как показать общий прогресс с rsync и нашёл полезный ответ из этого поста: https://stackoverflow.com/questions/7157973/monitoring-rsync-progress

В основном, вы можете использовать –info=progress2 в дев-версии rsync 3.1.0. Вот что написано в документации:

Есть также опция –info=progress2, которая выводит статистику на основе всей передачи, а не отдельных файлов. Используйте этот флаг без вывода имени файла (например, избегайте -v или указывайте –info=name0, если хотите видеть, как идет передача, не прокручивая экран с множеством имен. (Не нужно указывать опцию –progress, чтобы использовать –info=progress2.)

Используйте

lsof -ad3-999 -c rsync

Чтобы увидеть, какие файлы rsync в данный момент открывает (покажет размер файла) rsync копирует в скрытый файл локально

Я воспользовался ответом от zerodeux и написал свой собственный небольшой bash-скрипт:

#!/bin/bash

RSYNC="ionice -c3 rsync"
# не используйте --progress
RSYNC_ARGS="-vrltD --delete --stats --human-readable"
SOURCES="/dir1 /dir2 /file3"
TARGET="storage::storage"

echo "Выполняется проверка, чтобы увидеть, сколько файлов должно быть передано..."
TODO=$(${RSYNC} --dry-run ${RSYNC_ARGS} ${SOURCES} ${TARGET}|grep "^Number of files transferred"|awk '{print $5}')

${RSYNC} ${RSYNC_ARGS} ${SOURCES} ${TARGET} | pv -l -e -p -s "$TODO"

Если у вас нет последнего rsync (например, в OS X стоит 2.6.9) и вы не можете использовать --info=progress2, вот другой способ избежать страниц с прокручиваемым текстом о прогрессе:

rsync -aPh <source> <destination> | xargs -L1 printf "\33[2K\rTransferring: %s"

Это будет выводить, в одной строке, имя последнего файла, который передается:

Transferring: the-latest.file

Я воспользовался ответом от zerodeux и написал свой собственный bash-скрипт:

#!/bin/bash

RSYNC="ionice -c3 rsync"
# не используйте --progress
RSYNC_ARGS="-vrltD --delete --stats --human-readable"
SOURCES="/dir1 /dir2 /file3"
TARGET="storage::storage"

#echo "Выполняется проверка, чтобы увидеть, сколько файлов должно быть передано..."
TODO=$(find ${SOURCES} | wc -l)

${RSYNC} ${RSYNC_ARGS} ${SOURCES} ${TARGET} | pv -l -e -p -s "$TODO"

Я изменил проверку TODO на

TODO=$(find ${SOURCES} | wc -l)

Это быстро находит количество файлов!

Я создал индикатор прогресса для rsync в виде обертки. С --info=progress2 из новых версий rsync патчирование не требуется.

Используйте — замените rsync на rsyncy:

rsyncy -a FROM/ TO

rsyncy

Больше информации на GitHub, установить с помощью pip3 install --user rsyncy

Обратите внимание на то, что даже –info=progress2 не совсем надежен, так как этот процент основан на количестве файлов, о которых rsync ‘знает’ на момент отображения прогресса. Это не обязательно общее количество файлов, которые нужно синхронизировать (например, если он обнаруживает большое количество больших файлов в глубоко вложенной директории). Одним из способов обеспечения того, чтобы –info=progress2 не ‘подскакивал назад’ в показании прогресса, было бы заставить rsync просканировать все директории рекурсивно перед началом синхронизации (вместо его стандартного поведения по выполнению инкрементального рекурсивного сканирования), предоставив также опцию –no-inc-recursive. Однако имейте в виду, что эта опция также увеличит использование памяти и время выполнения rsync.

Я бы сделал это комментарием, но у меня недостаточно репутации. В ответ на комментарий naught101 к выбранному ответу опция –progress показывает, сколько файлов было передано из общего количества для передачи. Я не осознавал этого, пока не посмотрел на этот пост и не рассмотрел вывод более внимательно.

Статистика ‘to-check’ показывает, сколько файлов осталось из общего. Это наиболее полезно, когда вы rsync’ите на новое назначение, чтобы знать, что все файлы будут полностью скопированы.

Из страницы man:

Когда [каждая] передача файла завершается, rsync заменяет строку прогресса на строку сводки, которая выглядит так:

    1238099 100%  146.38kB/s    0:00:08  (xfer#5, to-check=169/396)

В этом примере файл имел общий размер 1238099 байт, средняя скорость передачи для всего файла составила 146.38 килобайта в секунду за 8 секунд, которые потребовались для завершения, это была 5-я передача обычного файла во время текущей сессии rsync, и осталось 169 файлов для проверки получателя (чтобы проверить, являются ли они актуальными или нет) из 396 файлов в общем списке файлов.

Я использую скрипт, который извлекает информацию из /proc//io для процесса rsync (или любого другого процесса). Зная общее количество данных для передачи, рассчитывает прогресс.

#!/bin/bash

usage()
{
   echo "usage: $0 PID BASEMSIZE [DELAY[s|m|h]]"
}

if [ $# -lt 2 ]; then
   usage
   exit 1
elif [ $# -eq 3 ]; then
   DELAY=$3
else
   DELAY=5s
fi

PID=$1
PBASE=`echo "scale=2; $2/1024"|bc`

R_PID=$PID
W_PID=$PID

R_SPEED_MAX=0
W_SPEED_MAX=0
R_SPEED_CUM=0
W_SPEED_CUM=0
R_SPEED_AVG=0
W_SPEED_AVG=0

ETA=0
ETA_H=0
ETA_M=0
ETA_S=0

while [ ! -r /proc/$PID/io ];
do
   clear
   echo "Ожидание появления процесса с PID=$PID!"
   sleep 1
done

B_READ_PREV=`cat /proc/$R_PID/io|awk '$1 ~ /^read_bytes/ {print $2}'`
B_WRITE_PREV=`cat /proc/$W_PID/io|awk '$1 ~ /^write_bytes/ {print $2}'`
T1=`date +%s.%N`

count=0
while true
do
   [ ! -r /proc/$PID/io ] && break
   clear
   B_READ=`cat /proc/$R_PID/io|awk '$1 ~ /^read_bytes/ {print $2}'`
   B_WRITE=`cat /proc/$W_PID/io|awk '$1 ~ /^write_bytes/ {print $2}'`
   BL_READ=`echo "scale=2; ($B_READ-$B_READ_PREV)/1048576"|bc`
   BL_WRITE=`echo "scale=2; ($B_WRITE-$B_WRITE_PREV)/1048576"|bc`
   GB_DONE=`echo "scale=2; $B_WRITE/1073741824"|bc`
   PDONE=`echo "scale=2; $GB_DONE*100/$PBASE"|bc`
   T2=`date +%s.%N`
   TLOOP=`echo "scale=2; ($T2-$T1)/1"|bc`
   R_SPEED=`echo "scale=2; $BL_READ/$TLOOP"|bc`
   W_SPEED=`echo "scale=2; $BL_WRITE/$TLOOP"|bc`

   if [ $count -ge 1 ]; then
      R_SPEED_CUM=`echo "scale=2; $R_SPEED_CUM+$R_SPEED"|bc`
      R_SPEED_AVG=`echo "scale=2; $R_SPEED_CUM/$count"|bc`
      W_SPEED_CUM=`echo "scale=2; $W_SPEED_CUM+$W_SPEED"|bc`
      W_SPEED_AVG=`echo "scale=2; $W_SPEED_CUM/$count"|bc`
      [ `echo "scale=2; $W_SPEED > $W_SPEED_MAX"|bc` -eq 1 ] && W_SPEED_MAX=$W_SPEED
      [ `echo "scale=2; $R_SPEED > $R_SPEED_MAX"|bc` -eq 1 ] && R_SPEED_MAX=$R_SPEED
   fi

   if [ `echo "scale=2; $W_SPEED_AVG > 0"|bc` -eq 1 ]; then
      ETA=`echo "scale=2; (($PBASE-$GB_DONE)*1024)/$W_SPEED_AVG"|bc`
      ETA_H=`echo "scale=0; $ETA/3600"|bc`
      ETA_M=`echo "scale=0; ($ETA%3600)/60"|bc`
      ETA_S=`echo "scale=0; ($ETA%3600)%60"|bc`
   fi

   echo "Мониторинг PID: $PID"
   echo
   echo "Чтение:       $BL_READ MiB за $TLOOP с"
   echo "Запись:      $BL_WRITE MiB за $TLOOP с"
   echo
   echo "Скорость чтения:  $R_SPEED MiB/c ( средняя: $R_SPEED_AVG, максимум: $R_SPEED_MAX )"
   echo "Скорость записи: $W_SPEED MiB/c ( средняя: $W_SPEED_AVG, максимум: $W_SPEED_MAX )"
   echo
   echo "Готово: $GB_DONE GiB / $PBASE GiB ($PDONE %)"
   [ `echo "scale=2; $ETA > 0"|bc` -eq 1 ] && printf "ETA: %02d:%02d:%05.2f (%.2fs)\n" $ETA_H $ETA_M $ETA_S $ETA
   echo "Прошло времени: `ps -p $PID -o etime=`"

   T1=`date +%s.%N`
   sleep $DELAY
   B_READ_PREV=$B_READ
   B_WRITE_PREV=$B_WRITE
   ((count++))
done
echo "----- Завершено -------------------------------------------------------------------"

Если ваша версия rsync не принимает опцию --info=progress2, вы можете использовать tqdm:

Для установки:

pip install tqdm

Для использования:

$ rsync -av /source /dest | tqdm --unit_scale | wc -l
10.0Mit [00:02, 3.58Mit/s]

Возможно, вы можете объединить pv с rsync. Особенно параметр --size может быть полезен. Загляните в документацию, что-то вроде pv --size $(du -sb . | awk '{print $1}') | rsync -av . host:/your/path должно сработать.

Здесь вы найдете документацию и программное обеспечение.

Я сам этого не пробовал.

Наверное, немного поздно, но будущие искатели ответов могут получить выгоду.

Это также меня беспокоило, поэтому я решил опуститься до деталей и написать свой первый скрипт. Пакет zenity должен быть установлен (sudo apt-get install zenity), но я уверен, что он, вероятно, уже есть. Также я использую wmctrl (управление оконным менеджером), чтобы изменить заголовок диалога с прогрессом, когда он завершается, его легко установить, но это не сыграет роли, если вы этого не сделаете. Мне просто нравится видеть, когда это завершено в моей панели.

Скрипт в основном запрашивает исходный и целевой каталог, вычисляет процент назначения по сравнению с исходным в размере с помощью du и отображает индикатор прогресса.

Примечание: это работает только для полной синхронизации каталогов/файлов (я обычно использую его для создания резервных копий кеша apt), поэтому опция –exclude=/file/in/Source-directory не применима. Также не будет работать, если в каталоге назначения есть файлы/каталоги, отсутствующие в каталоге источника. Я не уверен, работает ли это для удаленных источников/назначений, так как никогда не имел необходимости в этом или ресурсов для тестирования.

PS. Этот скрипт может быть очень плохо написан или очень неэффективен (я новичок в скриптах), но, по крайней мере, он выполняет свою задачу, и, конечно, вам добро пожаловать редактировать и улучшать его в соответствии с вашими потребностями. PSS. Я также не смог заставить кнопку отмены завершить rsync, поэтому я просто убрал её.

    #!/bin/bash
set -e;

WELC="Запуск RsyncP от имени $USER";

function echo_progress()
{
    while (($TRANSFER_SIZE > 1000));    
    do  
        DEST_SIZE=$(du -s $DEST_FOLDER | cut -d / -f 1); 
        ((TRANSFER_SIZE=$SOURCE_SIZE-DEST_SIZE)); 
        PROGRESS_PERC=$((DEST_SIZE*100/SOURCE_SIZE));
        echo $PROGRESS_PERC;
        sleep 0.1s;
    done;
    echo 100;
    zenity --info --width=250 --title=RsyncP --text="Синхронизация файлов завершена!";
}

function get_input()
{
    dirs=$(zenity --forms --width=500 --title="RsyncP" --text="Введите исходные и целевые каталоги" --add-entry="Источник: " --add-entry="Назначение: " --separator=" ");

    SOURCE_FOLDER=$(echo $dirs | cut -d' ' -f 1);
    DEST_FOLDER=$(echo $dirs | cut -d' ' -f 2);

    OPTIONS=-$(zenity --list --title="RsyncP Options" --text="Выберите параметры rsync" --separator="" --height=470 --width=470 --checklist --column "активировать" --column "Опция" --column "Описание" FALSE v "Подробно (только терминал)" FALSE q "Скрыть, подавить неошибочные сообщения (только терминал)" FALSE P "Прогресс (только терминал)" FALSE a "Архив (lrpog)" TRUE r "Рекурсивно в директориях" FALSE p "Сохранять права" FALSE o "Сохранять владельца" FALSE g "Сохранять группу" FALSE l "Копировать символьные ссылки как символьные ссылки");

    zenity --question --no-wrap --title="RsyncP" --width=500 --text="rsync  $OPTIONS $SOURCE_FOLDER $DEST_FOLDER\nВы хотите продолжить?";

    SOURCE_SIZE=$(du -s $SOURCE_FOLDER | cut -d / -f 1); 
    DEST_SIZE=$(du -s $DEST_FOLDER | cut -d / -f 1); 
    PROGRESS_PERC=$((DEST_SIZE*100/SOURCE_SIZE)); 
    TRANSFER_SIZE=1001;
}

if [ "$(id -u)" != "0" ]; then
    zenity --question --title=RsyncP --text="$WELC, Продолжить?";
    get_input;
    rsync  $OPTIONS $SOURCE_FOLDER $DEST_FOLDER & 
    echo_progress | zenity --progress --title=RsyncP --no-cancel --auto-close --text="Копирование из \n$SOURCE_FOLDER в \n$DEST_FOLDER" ;
else            
    zenity --question --title=RsyncP --text="$WELC, Продолжить?";
    get_input; 
    sudo rsync  $OPTIONS $SOURCE_FOLDER $DEST_FOLDER & 
    echo_progress | zenity --progress --title=RsyncP --no-cancel --auto-close --text="Копирование из \n$SOURCE_FOLDER в \n$DEST_FOLDER" ;
fi

Если у вас нет последнего rsync (например, в OS X стоит 2.6.9) и вы не можете обновить с помощью brew upgrade rsync, вам не нужно использовать –info=progress2, или другой альтернативой вы можете увидеть вывод файлов без дополнительных команд:

rsync -avh

–info=progress2 работает хорошо

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

#!/bin/bash

SOURCE=a
TARGET=b
TMP_F=/tmp/rsync.log
PARAMS="--info=progress2 --stats -r -tgo -p -l --update -H $SOURCE $TARGET"

display_total_copy_persent() {
    rsync --dry-run $PARAMS > $TMP_F
    total=`grep "^Total file size" $TMP_F | awk '{print $4}' | tr -d ','`
    trans=`grep "^Total transferred file size" $TMP_F | awk '{print $5}' | tr -d ','`
    if [ $total != 0 ]; then persent=$(($trans/($total/100))); fi
    printf "\033[0;32m[##################################################]\033[0m\n"
    printf "\033[0;32m[ Будет скопировано = \033[0;34m$persent%%\033[0;30m ]\n"
    printf "\033[0;32m[##################################################]\033[0m\n"
}

start_rsync_progress() {
    rsync $PARAMS
}

display_total_copy_persent
start_rsync_progress
> rsync --info=help

Используйте OPT или OPT1 для вывода уровня 1, OPT2 для уровня 2 и т.д.; OPT0 отключает.

BACKUP     Упоминание файлов, которые были сохранены
COPY       Упоминание файлов, скопированных локально на стороне получения
DEL        Упоминание удалений на стороне получения
FLIST      Упоминание списка файлов, получаемых/отправляемых (уровни 1-2)
MISC       Упоминание разнообразной информации (уровни 1-2)
MOUNT      Упоминание монтирований, которые были найдены или пропущены
NAME       Упоминание 1) обновленных имен файлов/директорий, 2) неизмененных имен
NONREG     Упоминание пропущенных нерегулярных файлов (значение по умолчанию 1, 0 отключает)
PROGRESS   Упоминание 1) прогресса по файлам или 2) общего прогресса передачи
REMOVE     Упоминание файлов, удалённых на стороне отправки
SKIP       Упоминание файлов, пропущенных из-за переопределений передачи (уровни 1-2)
STATS      Упоминание статистики в конце выполнения (уровни 1-3)
SYMSAFE    Упоминание небезопасных символических ссылок

ALL        Установить все --info опции (например, all4)
NONE       Тишина всех --info опций (то же, что и all0)
HELP       Вывод этого справочного сообщения

Опции, добавляемые на каждом уровне детализации:
0) NONREG
1) COPY,DEL,FLIST,MISC,NAME,STATS,SYMSAFE
2) BACKUP,MISC2,MOUNT,NAME2,REMOVE,SKIP

Таким образом, rsync --info=progress2 кажется наиболее разумным

Ответ или решение

Да, показывать общий прогресс при использовании rsync теперь возможно благодаря опции --info=progress2, которая была добавлена в версии 3.1.0. Эта опция выводит общую информацию о прогрессе переданных данных, вместо отображения прогресса для каждого отдельного файла.

Вот как можно использовать эту опцию:

rsync -a --info=progress2 /source /destination

При выполнении этой команды вы получите строку с процентом завершения, средней скоростью передачи и оставшимся временем. Например, вывод может выглядеть так:

305,002,533  80%   65.69MB/s    0:00:01  xfr#1653, ir-chk=1593/3594

Дополнительные рекомендации

  1. Опция --no-inc-recursive: Чтобы улучшить точность отображаемого прогресса, можно использовать опцию --no-inc-recursive, которая отключает инкрементную рекурсию. Это позволит rsync сначала составить полный список файлов, что даст более точный отчет о прогрессе, но увеличит потребление памяти и время начала передачи. Пример использования:

    rsync -a --info=progress2 --no-inc-recursive /source /destination
  2. Альтернативные подходы: Если у вас старая версия rsync, не поддерживающая --info=progress2, вы можете использовать сторонние утилиты, такие как pv (Pipe Viewer) или tqdm. Например, следующим образом:

    rsync -a /source /destination | pv -s $(du -sb /source | awk '{print $1}') > /dev/null

    Либо, используя tqdm:

    rsync -av /source /destination | tqdm --unit_scale | wc -l

Заключение

Таким образом, с помощью опции --info=progress2 в rsync вы можете получить общее отображение прогресса при выполнении сложных операций по синхронизации файлов. Это полезный инструмент, особенно при работе с большими объемами данных или при резервном копировании целых файловых систем.

Для получения дополнительной информации о других доступных опциях вы можете обратиться к официальной документации rsync, доступной по адресу rsync(1) man page.

Оцените материал
Добавить комментарий

Капча загружается...