
Я хотел бы отслеживать ход выполнения медленной операции с помощью pv
. Размер ввода этой операции известен заранее, а размер ее вывода — нет. Это заставило меня поместить pv
слева от операции в конвейере.
Проблема в том, что долго выполняющаяся команда немедленно потребляет весь свой ввод из-за буферизации. Это немного похоже наОтключить буферизацию в каналевопрос, но в моем случае медленнее всего идет операция потребления, а не производства, и ни один из ответов на другой вопрос, похоже, в этом случае не работает.
Вот простой пример, демонстрирующий проблему:
seq 20 | pv -l -s 20 | while read line; do sleep 1; done
20 0:00:00 [13.8k/s] [=====================================>] 100%
Вместо того чтобы обновляться каждую секунду, индикатор выполнения немедленно перескакивает на 100% и остается там в течение всех 20 секунд, необходимых для обработки ввода. pv
Прогресс можно было бы измерить только в том случае, если бы строки обрабатывались по одной, но весь ввод последней команды, похоже, считывается в буфер.
Несколько более длинный пример, который также демонстрирует неизвестное количество выходных строк:
#! /bin/bash
limit=10
seq 20 | \
pv -l -s 20 | \
while read num
do
sleep 1
if [ $num -gt $limit ]
then
echo $num
fi
done
Есть предложения по обходному пути? Спасибо!
решение1
В вашей настройке данные прошли, pv
пока они все еще обрабатываются на правой стороне. Вы можете попробовать перейти pv
на самую правую сторону следующим образом:
seq 20 | while read line; do sleep 1; echo ${line}; done | pv -l -s 20 > /dev/null
Обновлять: Что касается вашего обновления, возможно, самым простым решением будет использовать именованный канал и подоболочку для отслеживания хода выполнения:
#! /bin/bash
trap "trap - SIGTERM && kill -- -$$" SIGINT SIGTERM EXIT
(rm /tmp/progress.pipe; mkfifo /tmp/progress.pipe; tail -f /tmp/progress.pipe | pv -l -s 20 > /dev/null)&
limit=10
seq 20 | \
while read num
do
sleep 1
if [ $num -gt $limit ]
then
echo $num
fi
echo $num > /tmp/progress.pipe
done