¿Cómo realizar un seguimiento del progreso de un comando en una tubería si solo se conoce de antemano el tamaño de su entrada?

¿Cómo realizar un seguimiento del progreso de un comando en una tubería si solo se conoce de antemano el tamaño de su entrada?

Me gustaría realizar un seguimiento del progreso de una operación lenta utilizando pv. El tamaño de la entrada de esta operación se conoce de antemano, pero el tamaño de su salida no. Esto me obligó a ponerme pva la izquierda de la operación en la tubería.

El problema es que el comando de ejecución prolongada consume inmediatamente toda su entrada debido al almacenamiento en búfer. Esto es algo similar a laDesactivar el almacenamiento en búfer en la tuberíapregunta, pero en mi caso es la operación de consumo la que es lenta, no la de producción y ninguna de las respuestas a la otra pregunta parece funcionar en este caso.

A continuación se muestra un ejemplo sencillo que demuestra el problema:

seq 20 | pv -l -s 20 | while read line; do sleep 1; done
  20 0:00:00 [13.8k/s] [=====================================>] 100%

En lugar de actualizarse cada segundo, la barra de progreso salta inmediatamente al 100% y permanece allí durante los 20 segundos que lleva procesar la entrada. pvSolo podría medir el progreso si las líneas se procesaran una por una, pero toda la entrada del último comando parece leerse en un búfer.

Un ejemplo algo más largo que también demuestra el número desconocido de líneas de salida:

#! /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

¿Alguna sugerencia para una solución alternativa? ¡Gracias!

Respuesta1

En su configuración, los datos pasaron pvmientras aún se procesan en el lado derecho. Podrías intentar moverte pvhacia el lado derecho de esta manera:

seq 20 | while read line; do sleep 1; echo ${line}; done | pv -l -s 20 > /dev/null

Actualizar: Con respecto a su actualización, tal vez la solución más sencilla sea utilizar una canalización con nombre y un subshell para monitorear el progreso:

#! /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

información relacionada