web-dev-qa-db-ja.com

入力のサイズのみが事前にわかっている場合、パイプ内のコマンドの進行状況をどのように追跡しますか?

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は、行が1つずつ処理された場合にのみ進行状況を測定できましたが、最後のコマンドの入力全体がバッファーに読み込まれたようです。

不明な数の出力行も示す、やや長い例:

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

回避策の提案はありますか?ありがとう!

5
Zoltan

セットアップでは、データはpvを通過しましたが、右側で処理されています。次のように、pvを右端に移動してみてください。

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

pdate:更新に関して、おそらく最も簡単な解決策は、名前付きパイプとサブシェルを使用して進行状況を監視することです。

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