Вопрос или проблема
Я использую команду 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.
Пример
Ваша задача состоит в том, чтобы выполнить следующее:
- Считать прогресс и скорость передачи данных с помощью
pv
. - Обновить прогресс и скорость передачи в унифицированной форме.
- Преобразовать скорость передачи в мегабиты в секунду.
- Внести данные в базу данных.
Пример команды 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), и обновлять эти данные в базе данных для аналитики и дальнейшего использования.
Таким образом, этот подход не только улучшает визуальную обратную связь во время выполнения процесса, но и улучшает управляемость данными для их последующего анализа и принятия решений.