Linux 的 pv
指令可以讓使用者即時監看通過管線(pipe)的資料量。
一個 Linux 系統管理者通常都會花許多時間在終端機上管理系統,例如使用各種指令進行安裝或移除系統套件、查看系統負載狀況、複製與搬移等檔案操作,還有其他各式各樣的動作都可以在終端機中達成。
有一些指令在執行時不會特別輸出一些進度的相關資訊,如果執行的時間比較常時,使用者無從得知指令的執行狀況,常會懷疑指令是否已經當掉了。
大部分的 Linux 指令都不會提供執行進度的輸出訊息,但是執行進度是使用者常常會想要看的東西,遇到這樣的狀況我們可以使用
pv
指令來產生有用的進度訊息,讓一般的指令加上進度顯示的功能,以下是 pv
指令的使用方式與範例。
安裝
在 Ubuntu Linux 上若要安裝 pv
,可以使用 apt:
sudo apt-get install pv
若在 Red Hat 系列的 Linux 上安裝 pv
,則使用 yum
:
yum install pv
FreeBSD 的使用者可以透過 port 安裝:
cd /usr/ports/sysutils/pv/ make install clean
或是直接安裝編譯好的版本:
pkg_add -r pv
使用 pv
顯示程式執行進度
pv
的角色就跟 cat
類似,一般 cat
可以將資料從檔案或是標準輸入(stdin)讀取進來,然後從標準輸出(stdout)輸出,而 pv
也是一樣,只是它在輸入與輸出中間會自動將進度顯示在終端機上。
舉例來說,假設我們要將一個檔案內容導向另外一個檔案,可以這樣寫:
cat file > other_file
如果 file
這個檔案很大的時候(例如一個 iso 影像檔),這種指令會需要等待一段時間,沒有任何輸出,這時候就可以改用 pv
,變成這樣:
pv file > other_file
將 cat
的位置替換為 pv
之後,就會顯示資料的處理進度。我拿 Ubuntu Linux 16.04 的 iso 檔作為示範,將其導入 /dev/null
:
pv ubuntu-16.04-desktop-amd64.iso > /dev/null
在導向資料的過程中,pv
就會產生這樣的進度輸出:
pv
的基本使用方式就是這樣,實際運用上可以結合 Linux 中其它的指令一起使用,以下是一些常用的範例。
pv
使用範例
使用 gzip
壓縮資料時不會有任何進度指示,我們可以藉由 pv
來顯示進度:
pv file | gzip > file.gz
如果要從其他的行程(process)讀取資料來傳送,也可以用管線(pipe)的方式將 pv
串在中間:
cat file | pv | gzip > file.gz
不過在這種情況下 pv
就無法判斷整個完整資料的大小,所以無法計算整體進度,只會顯示經過的時間以及資料處理的速度。如果完整的資料大小是已知的,可以使用 -s
指定資料大小,這樣 pv
就會計算整體的進度(以百分比表示):
cat file | pv -s 1513308160 | gzip > file.gz
pv
若配合 dialog
這個小工具就可以製作出文字介面的進度視窗:
(pv -n file | gzip > file) 2>&1 | dialog --gauge "Please wait..." 10 70 0
這裡的 -n
參數是可以讓 pv
直接輸出單純的百分比數字,因為 pv
的訊息預設會輸出至標準錯誤(stderr),所以我們要加上 2>&1
讓標準錯誤導向標準輸出,然後將標準輸出導向 dialog
產生文字的進度視窗。
如果有許多的處理動作串在一起,可以加上多個 pv
監看不同處理步驟的狀況:
pv -cN raw file | gzip | pv -cN gzip > file.gz
使用 netcat 傳送資料時也不會有任何進度指示,一樣可以藉由 pv
來顯示進度:
pv file | nc 192.168.0.1 3000 cat file | pv | nc 192.168.0.1 3000 cat file | pv -s 12345 | nc 192.168.0.1 3000 (pv -n file | nc 192.168.0.1 3000) 2>&1 | dialog --gauge "Please wait..." 10 70 0
計算 MD5 與 SHA1 校驗碼:
pv file | md5sum pv file | sha1sum
備份 /dev/sda
磁碟,跳過錯誤:
pv -EE /dev/sda > disk-image.img
將映像檔寫回磁碟:
pv disk-image.img > /dev/sda
抹除磁碟上所有的資料,這個主要用於丟棄硬碟之前,把資料徹底清除,避免資料外洩:
pv < /dev/zero > /dev/sda