コマンド入力のサイズだけが既知である場合、パイプラインでコマンドの進行状況をどのように追跡できますか?

コマンド入力のサイズだけが既知である場合、パイプラインでコマンドの進行状況をどのように追跡できますか?

遅い作業の進行状況を追跡するために使用したいと思います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秒間そのまま残ります。pv1行ずつ処理すると進行状況のみを測定できますが、最後のコマンドの入力全体がバッファに読み込まれるようです。

より長い例では、不明な数の出力ラインも示しています。

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

おすすめ記事