
我有大量大文件(數百個文件,每個文件數百 MB),我需要透過許多程式來過濾和轉換它們。我正在利用多個 CPU 核心,因此我在每個文件上運行同一管道的多個實例(最多可以有一百個核心,並且可以使用 ssh 作為管道的一部分,以防這對回答)。我想監控每個管道,我正在pv
為此使用。這是我所擁有的一個最小範例:
$ pv file-001.gz | gunzip | xz > file-001.xz
1.58GB 0:00:02 [ 713MB/s] [=================================>] 100%
實際上,我還在管道中做了其他幾件事,包括通過ssh 將數據傳遞到其他計算機,並將其通過這些計算機上的過濾器進行管道傳輸,但管道始終會以重定向到主主機上的新文件結束。此外,管道中的任何階段都不需要整個資料集;它們可以逐行或逐塊地操作。
目前,我需要為管道的每個實例提供一個單獨的終端視窗。我想做的是在單一終端機/shell 中啟動管道的 n 個並行實例,並從每個 pv 實例的一行中獲取輸出。像這樣的事情:
1.48GB 0:00:54 [ 704MB/s] [===============================> ] 97% ETA 00:00:06
1.58GB 0:01:00 [ 713MB/s] [=================================>] 100%
0.75GB 0:00:31 [ 709MB/s] [================> ] 50% ETA 00:00:29
n 的值是終端機視窗中可以容納的行數,例如 3-50 左右。進度報告的具體格式並不重要,只要它包括速度、完成百分比、已用時間和預計剩餘時間即可。我使用什麼也不重要pv
,使用其他程式也可以,只要我可以輕鬆安裝它或只是簡單的 shell(最好是 bash)。但重要的是,該方法可以處理偶爾破裂的管道,以防管道的一部分因某種原因崩潰。我還想在每次作業完成(成功與否)時開始新的作業,並且仍然有未處理的文件。
關於如何做到這一點有什麼想法嗎?
請注意,我已經嘗試過GNU 平行,但它的 ssh 功能似乎假設每個輸入檔案首先傳輸到遠端主機,然後進行處理,然後將結果傳回,我想避免這種情況,因為涉及的資料量和每次處理的空間量有限節點。
答案1
關於如何做到這一點有什麼想法嗎?
不。
pv 有 -c 和 -N 選項,應該可以讓你做你想做的事
$ pv -cN source access.log | gzip | pv -cN gzip > access.log.gz
source: 760MB 0:00:15 [37.4MB/s] [=> ] 19% ETA 0:01:02
gzip: 34.5MB 0:00:15 [1.74MB/s] [ <=> ]
但我不知道如何將該功能應用於多個管道
但是,如果您查看 pv 的手冊頁,您會看到這一點
(tar cf - . \
| pv -n -s $(du -sb . | awk '{print $1}') \
| gzip -9 > out.tgz) 2>&1 \
| dialog --gauge 'Progress' 7 70
因此,只要可以在一組小視窗中查看進度,您就可以擴展它以並行運行多個任務。我會嘗試Xdialog。
目前,我需要為管道的每個實例一個單獨的終端窗口
我的主要觀點是,您沒有必要以互動方式打開大量終端窗口,您可以讓一個腳本本身打開許多對話框。
答案2
你看過--pipe
GNU Parallel 嗎?
cat bigfiles* | pv | parallel --pipe -S server1,server2 'cat | process_pipe'
(包括貓以強調)
預設為 1 MB 區塊大小,可以使用 --block 進行調整。
-- 編輯 1-1 對應關係 --
根據以上內容,您可以得到如下 1-1 對應:
parallel --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*
(包括貓以強調)
這並不是最優的,因為內部並行不會知道其同級,因此可能會在 server1 上產生比 server2 更多的並行。避免這種情況的一種方法是在外部並行上設定 -j1,但如果內部並行只有足夠的區塊用於第一台伺服器,則這不是最佳選擇。換句話說:為了完美平衡你的工作負載,你可能需要稍微調整一下 - 甚至可能使用 --load 100% 或類似的。
---編輯:處理崩潰---
如果process_pipe
傳回錯誤,則應再重試該指令 2 次:
parallel --retries 3 --eta "cat {} | parallel --pipe -S server1,server2 'cat | process_pipe' > {}.out" ::: bigfiles*