pv 入門 - パイプの進捗をプログレスバーで見る

pv 入門 - パイプの進捗をプログレスバーで見る

pv とは何か?

結論: pv(Pipe Viewer)はパイプを流れるデータ量を計測し、プログレスバー・経過時間・転送速度・ETA をリアルタイム表示するツール。ddcp で「進んでいるのか分からない」不安を解消する。

ddgziptarmysql などにデータを流し込むと、完了まで何の出力もなく無言で固まったように見える。pv はパイプの途中に挟むだけで、いま何バイト処理し、残り何秒で終わるかを可視化する。

$ pv bigfile.iso | dd of=/dev/sdb
 1.2GiB 0:00:42 [29.0MiB/s] [=========>          ] 48% ETA 0:00:45

表示される 6 項目はそれぞれ次を意味する。

  • 1.2GiB: ここまでに転送したバイト数
  • 0:00:42: 経過時間
  • [29.0MiB/s]: 現在の転送速度
  • [====>]: プログレスバー
  • 48%: 進捗率
  • ETA 0:00:45: 完了までの予測時間

この記事で身につくこと

  • パイプの進捗をプログレスバーで見る基本形
  • サイズ不明なパイプでも ETA を出す -s の使い方
  • 速度制限・行数計測・実行中プロセス監視といった実務テクニック

pv はどうインストールするのか?

結論: pv は標準では入っていないことが多い。Debian/Ubuntu は apt、RHEL 系は dnf、macOS は brew で導入する。

# Debian / Ubuntu
$ sudo apt install pv

# RHEL / Rocky / AlmaLinux / Fedora
$ sudo dnf install pv

# macOS (Homebrew)
$ brew install pv

導入確認:

$ pv --version
pv 1.6.20

多くの最小構成サーバーには pv が入っていない。command not found が出たら上記でインストールする。本番サーバーに勝手に追加できない場合は、後述の -d(実行中プロセス監視)で代替できることがある。

基本的な使い方は?

結論: 引数にファイルを渡すと pv がサイズを自動把握し、進捗率と ETA まで表示する。パイプの「途中」に置くのが基本の型。

ファイルを渡す(サイズ自動検出)

ファイル名を直接渡すと、pv はそのサイズを stat で取得するため、進捗率と ETA が出る。

$ pv access.log | grep "404" > errors.txt

cat の代わりに pv を使う、と覚えればよい。

パイプの途中に挟む

すでにパイプがある場合は、計測したい箇所に挟み込む。

$ gzip -dc backup.sql.gz | pv | mysql mydb

この場合 pv は標準入力から読むためサイズが分からず、進捗率と ETA は出ない(転送量・経過時間・速度のみ表示)。ETA まで出したいときは次の -s を使う。

サイズが分からないパイプで ETA を出すには?

結論: 標準入力経由でサイズ不明なときは -s で想定サイズを明示する。du や圧縮前サイズと組み合わせると ETA が出せる。

-s--size)に総バイト数を渡すと、pv はそれを 100% として進捗率と ETA を計算する。k/m/g の接尾辞が使える。

$ pv -s 2g backup.sql.gz | gunzip | mysql mydb

ディレクトリを tar で固める場合は、du で実サイズを求めて渡すのが定番。

$ tar -cf - mydir | pv -s "$(du -sb mydir | cut -f1)" > mydir.tar

du -sb はバイト単位の合計サイズを返す(-b = bytes)。cut -f1 でサイズ列だけ取り出して -s に渡している。圧縮するとサイズは縮むため、gzip を通す場合 ETA は目安として捉える。

表示項目をカスタマイズするには?

結論: 表示要素はフラグで選べる。-p 進捗バー / -t 経過時間 / -e ETA / -r 速度 / -b バイト数 / -N 名前付け。何も付けなければ全部入り。

オプションを 1 つでも指定すると、指定した要素だけが表示される。

フラグ 表示内容
-p プログレスバー
-t 経過時間
-e ETA(残り時間)
-r 現在の転送速度
-a 平均転送速度
-b 転送バイト数
-N 名前ラベル付与

複数の pv を 1 行に並べるときは -N で名前を付けると区別しやすい。

$ pv -N "読み込み" -cb source.dat | gzip | pv -N "圧縮後" -cb > out.gz

-n--numeric)を使うと進捗率を「数値のみ」で出力するため、シェルスクリプトや dialog --gauge への入力に向く。

$ pv -n bigfile 2>&1 >/dev/null | while read p; do echo "進捗 $p%"; done

転送速度を制限するには?

結論: -L--rate-limit)で帯域を上限指定できる。本番ディスクやネットワークへの負荷を抑えたいコピーに有効。

$ pv -L 10m bigfile.iso > /mnt/backup/bigfile.iso

この例では転送速度を毎秒 10MiB に制限する。バックアップ中にディスク I/O や回線を食いつぶしてサービスへ影響を与えたくない場面で使う。

-L の値は 1 秒あたりのバイト数。10m は 10MiB/s であり 10Mbps(ビット毎秒)ではない。ネットワーク帯域の単位と混同しやすいので注意。

行数ベースで進捗を見るには?

結論: -l--line-mode)でバイト数ではなく行数をカウントする。ログ処理やレコード件数の進捗把握に向く。

$ pv -l -s 1000000 access.log | grep "POST" > posts.log

-s に総行数を渡せば「100 万行中いま何行目か」を進捗率で表示できる。行数が事前に分かるバッチ処理やインポートで便利。

複数段のパイプを個別に監視するには?

結論: パイプの複数箇所に pv を置く場合は -c--cursor)を併用する。-c がないと表示が衝突して崩れる。

$ pv -cN "入力" raw.dat | gzip | pv -cN "出力" > raw.gz

-c は端末のカーソル位置を制御し、複数の pv が別々の行に進捗を描くようにする。-N の名前ラベルと組み合わせて、どの段の進捗かを明示する。

実行中のプロセスの進捗を見るには?

結論: すでに走っている cpdd の進捗は pv -d PID で後付け監視できる。pv を最初から挟み忘れたときの救済策。

-d--watchfd)に PID を渡すと、そのプロセスが開いている全ファイルディスクリプタの読み書き進捗を表示する。

# 別端末で動いている dd の PID を調べる
$ pgrep -a dd
4821 dd if=/dev/sda of=backup.img bs=1M

# その進捗を後から覗く
$ pv -d 4821

特定のファイルディスクリプタだけを見たい場合は PID:FD 形式で指定する。

$ pv -d 4821:1

pv -d は対象プロセスの /proc/<PID>/fd/proc/<PID>/fdinfo を読んで進捗を推定する。Linux 限定の機能で、長時間の cpddgzip を「挟み忘れた」ときの定番リカバリ手段。

よくあるトラブルと対処は?

結論: 進捗率が出ない・ETA が表示されないの大半は「サイズ不明」が原因。-s で補うか、ファイル引数を直接渡す形に変える。

進捗率(%)と ETA が出ない

標準入力から読んでいてサイズが分からないため。ファイルを直接 pv file で渡すか、-s で想定サイズを与える。

command not found: pv

未インストール。インストール手順を参照。本番に追加できない場合は pv -d PID での外部監視を検討する。

バーが一瞬で 100% になる

データ量が小さいか、-s に指定したサイズが実データより小さい。-s の値が正しいか確認する。

bash: /usr/bin/pv: Argument list too long

これは pv 自体ではなくシェルの展開上限。pv でファイルを大量展開せず、find ... | pv -l | xargs のように行ストリームで渡す。

まとめ:次に読む

pv はパイプに 1 つ挟むだけで、無言だった処理が「あと何秒で終わるか」を語り出す。dd でのイメージ書き込み、tar/gzip でのバックアップ、mysql へのインポートなど、長時間ジョブの体感が一変する。まずは catpv に置き換えるところから始めるとよい。