
Gostaria de acompanhar o progresso de uma operação lenta usando o pv
. O tamanho da entrada desta operação é conhecido antecipadamente, mas o tamanho da sua saída não. Isso me forçou a colocar pv
à esquerda da operação no cano.
O problema é que o comando de longa execução consome imediatamente toda a sua entrada devido ao buffer. Isto é um pouco semelhante aoDesative o buffer no pipepergunta, mas no meu caso é a operação de consumo que é lenta, não a de produção e nenhuma das respostas para a outra pergunta parece funcionar neste caso.
Aqui está um exemplo simples que demonstra o problema:
seq 20 | pv -l -s 20 | while read line; do sleep 1; done
20 0:00:00 [13.8k/s] [=====================================>] 100%
Em vez de ser atualizada a cada segundo, a barra de progresso salta imediatamente para 100% e permanece lá durante os 20 segundos necessários para processar a entrada. pv
só poderia medir o progresso se as linhas fossem processadas uma por uma, mas toda a entrada do último comando parece ser lida em um buffer.
Um exemplo um pouco mais longo que também demonstra o número desconhecido de linhas de saída:
#! /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
Alguma sugestão para uma solução alternativa? Obrigado!
Responder1
Na sua configuração, os dados passaram pv
enquanto ainda são processados no lado direito. Você poderia tentar mover pv
para o lado direito assim:
seq 20 | while read line; do sleep 1; echo ${line}; done | pv -l -s 20 > /dev/null
Atualizar: Em relação à sua atualização, talvez a solução mais fácil seja usar um pipe nomeado e um subshell para monitorar o progresso:
#! /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