Как отслеживать ход выполнения команды в конвейере, если заранее известен только размер ее входных данных?

Как отслеживать ход выполнения команды в конвейере, если заранее известен только размер ее входных данных?

Я хотел бы отслеживать ход выполнения медленной операции с помощью 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

Связанный контент