Команда PV для отображения прогресса в Dialog со скоростью передачи в Мбит/с

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

Я использую команду PV -n для чтения разделов и использую gzip с каналом для сжатия прочитанных данных и сохранения файла. Пока данные читаются и записываются, я использую цикл while для отображения прогресса с помощью утилиты диалога Linux.

Это работает отлично, прогресс обновляется. Я также хочу отображать скорость передачи/чтения в Мбитах. Также я хочу обновлять таблицу базы данных с прогрессом и скоростью передачи в Мбитах.

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

        (pv -n /dev/$partitions | gzip -c >$path/${filename// /_}-${partitions}.img.gz) 2>&1 | while IFS= read -r progress;
                                do
                                        echo "processing /dev/$partitions currently completed $progress" >/run/log.log
                                        echo $progress | dialog --title "Capturing OS image of $hdd" --gauge " now creating image of HDD $hdd writing $filename Image, please wait...\n\n\n
                                        Processing Partition $i of $totalparts\n\n
                                        This process may take some time to complete\n\n" 13 90 0

mysql -u root -pxxxxxx dbi -h localhost | insert into speed(progress, speed) Values ("$line", "mbits")
                                    done

если я использую команду pv -n, она возвращает только числовое значение прогресса на новой строке. Смотрите пример ниже:

( /data/pv -n /dev/nvme0n1p1 | gzip -c >/run/test.img ) 
5
9
29
67
100

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

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

(pv -rep /dev/nvme0n1p1 | gzip -c >/run/test.img ) 
[4.9MiB/s] [====>                             ]  4% ETA 0:00:19

Идеальным выводом должен быть следующий.

(pv -rep /dev/nvme0n1p1 | gzip -c >/run/test.img ) 
[ 4.18MiB/s] [====>                          ]  14% ETA 0:00:19
[14.49MiB/s] [===========>                   ]  54% ETA 0:00:19
[24.39MiB/s] [========================>      ]  74% ETA 0:00:19
[44.29MiB/s] [===========================>   ]  78% ETA 0:00:19
[46.19MiB/s] [=============================> ]  98% ETA 0:00:19
[57.99MiB/s] [==============================>]  100% ETA 0:00:19

Я могу использовать AWK, Sed и Grep для форматирования необходимой информации и использования ее в своем цикле while. Но как я могу добиться того, чтобы это работало.

Если я использую pv -F $’%t %r %e\n’, я получаю желаемые результаты. Но я не могу использовать команды AWK, grep или tr. Смотрите пример ниже, он не возвращает ничего.

(pv -F $'%t %r %e\n' /dev/nvme0n1p1 | gzip -c >/run/test.img ) 2>&1 | tr -d ':[]'

Также, если я не перенаправляю stderr в stdout, с той же командой выше, я не получаю желаемых результатов, см. ниже, используя tr -d для удаления следующих символов “:[]”, но не работает.

 (pv -F $'%t %r %e\n' /dev/nvme0n1p1 | gzip -c >/run/test.img ) | tr -d ':[]'
0:00:01 [25.2MiB/s] ETA 0:00:18
0:00:02 [23.7MiB/s] ETA 0:00:18
0:00:03 [ 100MiB/s] ETA 0:00:07
0:00:04 [ 199MiB/s] ETA 0:00:01

Если я использую другие аргументы, такие как pv -n -r -e, он игнорирует все другие параметры и просто возвращает числовое значение прогресса на новой строке.

Возможно, есть альтернатива pv, которую я могу использовать для достижения точно описанного выше, или, возможно, кто-то может помочь с командой pv.

Используйте -F для форматирования вывода:

Например:

pv -F "%T %t %r %e"

Даст вам процентное время, затраченное на скорость и ETA

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

Использование команды pv в Unix-системах для отображения прогресса и скорости передачи данных — это достаточно полезное решение, особенно в контексте сжатия данных с помощью gzip и дальнейшего обновления базы данных. В приведённом вами случае, задача состоит в том, чтобы не только отображать прогресс, но и фиксировать скорость передачи в мегабитах в секунду (Mbps) и использовать эти данные для обновления таблицы в базе данных.

Теория

Команда pv, что расшифровывается как "Pipe Viewer", изначально предназначена для мониторинга процесса передачи данных через конвейеры (pipes) UNIX. Она предоставляет информацию о текущей скорости передачи, объёме переданных данных, проценте выполненной работы и предполагаемом времени до завершения операции. Форматирование вывода в pv может быть настроено с помощью различных флагов, таких как -F, -n, -r и так далее.

Использование pv с ключами -r (для отображения скорости) и -e (для отображения оставшегося времени) позволяет сформатировать вывод таким образом, чтобы отобразить всю нужную информацию в одном потоке данных. Однако, основная проблема заключается в корректном парсинге этого вывода и преобразовании его в строку, которая может быть удобно обработана в скрипте bash.

Пример

Ваша задача состоит в том, чтобы выполнить следующее:

  1. Считать прогресс и скорость передачи данных с помощью pv.
  2. Обновить прогресс и скорость передачи в унифицированной форме.
  3. Преобразовать скорость передачи в мегабиты в секунду.
  4. Внести данные в базу данных.

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

pv -F "%t %r %e" /dev/nvme0n1p1 | gzip -c > /run/test.img.gz 2>&1 | while IFS= read -r line; do
    timestamp=$(echo $line | cut -d ' ' -f 1)  # Извлечение времени
    rate=$(echo $line | cut -d ' ' -f 2 | tr -d '[]')  # Извлечение скорости
    eta=$(echo $line | cut -d ' ' -f 3)  # Извлечение ETA

    # Преобразование скорости из MiB/s в Mbps
    if [[ $rate =~ ^[0-9]+(\.[0-9]+)?MiB/s$ ]]; then
        rate_value=${rate%MiB/s}
        rate_mbps=$(bc <<< "scale=2; $rate_value * 8")
    fi

    # Запись в лог для отладки
    echo "Прогресс: $timestamp, Скорость: $rate ($rate_mbps Mbps), Оставшееся время: $eta" >> /run/log.log

    # Занесение данных в базу
    mysql -u root -pxxxxxx dbi -h localhost -e "INSERT INTO speed(progress, speed) VALUES ('$timestamp', '$rate_mbps')"
done

Применение

Для успешного выполнения данного сценария следует учесть следующие детали:

  • Парсинг выходных данных: Извлечение необходимых частей строки, таких как время, скорость и время до завершения, является критически важной задачей. Использование встроенных в bash инструментов вроде cut, tr и bc обеспечивает возможность преобразования и обработки строк.

  • Конвертация единиц: Преобразование скорости из мегабайтов в мегабиты требует математических операций, поскольку 1 MiB/s соответствует 8 Mbps. Такое преобразование можно легко сделать с помощью bc, что позволяет корректно преобразовать и использовать полученные данные.

  • Интеграция с диалогом и базой данных: Для пользовательского интерфейса, используйте dialog для визуальной обратной связи, а mysql для обновления базы данных.

На практике, применение вышеописанного скрипта позволит получить требуемый функционал: отображать прогресс операции, фиксировать скорость передачи в требуемых единицах (Mbps), и обновлять эти данные в базе данных для аналитики и дальнейшего использования.

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

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

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