好用的parallel命令
簡介
有時,我們需要處理一批數據,使用while循環是個不錯的想法,但while循環中的命令是一個一個執行的,如果要批量處理的數據很多,執行時間就會很長,而parallel可以讓命令并行執行,從而縮短命令執行時間。
下面,我們先用ncat來模擬一個處理數據的接口。
模擬接口
ncat -lk 8088 -c 'sleep 1;printf "HTTP/1.1 200 OK\r\nContent-Type: plain/text\r\nContent-Length: 3\r\n\r\nok\n"' 復制代碼此接口直接睡眠1秒,然后返回一個ok,表示數據處理成功。
調用接口
curl -X POST http://localhost:8088/user/add -d '{"user_id": 1, "user_name":"u1"}' 復制代碼測試數據
假設有10條數據,在data.txt中,如下:
1 u1 2 u2 3 u3 ... 復制代碼使用while循環處理
$ time while read -r -a line; docurl -X POST http://localhost:8088/user/add -d '{"user_id": '${line[0]}', "user_name":"'${line[1]}'"}'done < data.txt ok ok ok ok ok ok ok ok ok okreal 0m10.276s user 0m0.094s sys 0m0.096s 復制代碼使用while循環處理,其中time命令用來計時,real表示while命令的執行時間,可以看到,處理完10條數據花了約10秒,接下來我們使用parallel并發執行。
使用parallel并發執行
$ time cat data.txt | parallel -j10 -C '\s+' curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\' ok ok ok ok ok ok ok ok ok okreal 0m1.205s user 0m0.203s sys 0m0.060s 復制代碼使用parallel命令并發執行curl,-j10表示最多10個并發進程,-C '\s+' 表示使用空白來拆分每行(注:\s+是表示空白的正則表達式),這樣就可以使用{1}表示第1列,{2}表示第2列了,如我們所預期的,10條數據使用10個并發,處理完約1秒。
有用的--tag選項
上例的接口很簡單,直接返回ok,但在有大量數據需要處理時,有可能出現部分數據處理失敗,像上面的執行結果中,就很難知道是哪些數據處理失敗了,還好parallel提供了--tag選項,可以將處理的數據與執行結果都打印出來,如下:
$ cat data.txt | parallel -j10 -C '\s+' --tag curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {1}, \"user_name\":\"{2}\"}\' 1 u1 ok 2 u2 ok 4 u4 ok 3 u3 ok 5 u5 ok 6 u6 ok 7 u7 ok 8 u8 ok 9 u9 ok 10 u10 ok 復制代碼這樣,什么數據執行對應什么結果,就一目了然了。
查看進度
如果有大量數據需要處理,處理時能直觀的看到一個進度就再好不過了,parallel提供了3個查看進度的選項,--bar、--progress和--eta,一般使用--bar、--progress即可。
其中--bar適合待處理數據量確定的場景,因為parallel需要讀取所有數據后才能根據數據總量計算進度條。
而--progress適合待處理數據量未知的場景,只能看到已經處理了多少條數據,如下:
--joblog與--resume-failed選項
相信當你使用腳本處理有一定數據量的數據時,一定會遇到數據偶爾處理失敗的情況(由于網絡不穩定),這時你需要將處理失敗的數據再次找出來,然后再次處理,過程還是挺麻煩的。
好在parallel命令已經考慮到了這種場景,并提供了--joblog與--resume-failed選項,當有失敗產生時,你只需要再次執行整個命令行即可。
--semaphore選項
parallel既然提供了并發,那么必然會遇到并發沖突問題,比如sed命令就不支持并發的修改同一文件,不過parallel已經提供了--semaphore選項來解決這個問題了。
如下,其中sem是parallel --semaphore的別名,與其是等價的。
這里的邏輯是,每處理成功data.txt中的一條數據,就使用sed將data.txt中的那行數據末尾加一個ok,表示執行成功,然后在前面使用grep找不包含ok的數據,就達到了命令每次都處理未處理或處理失敗數據的邏輯。而sem -j1保護了sed,避免sed命令并發執行。
與mysql結合使用
parallel還可以和mysql結合使用,將任務導入mysql中或是執行mysql中的任務,如下:
# 1.將任務數據導入到pardb庫的paralleljobs表中,pardb庫需要事先自行創建 cat data.txt |parallel --sqlmaster 'sql:mysql://user:pass@localhost:3306/pardb/paralleljobs'# 2.執行paralleljobs表中待處理任務,Exitval=-1000為待處理任務 function deal_data(){p=($*)res=$(curl -s -X POST http://localhost:8088/user/add -d '{"user_id": '${p[0]}', "user_name":"'${p[1]}'"}')echo "$res"[[ "$res" == "true" ]] && return 0 || return 1 } export -f deal_dataparallel --sqlworker 'sql:mysql://user:pass@localhost:3306/pardb/paralleljobs' --tag deal_data 復制代碼處理csv數據
parallel命令還能很方便的處理csv文件數據,比如將data.txt改為data.csv,如下:
$ cat data.csv user_id,user_name 1,u1 2,u2 3,u3 ... # 使用--header : 選項來讀取csv的表頭,然后就可以{user_id},{user_name}來占位命令參數了 $ cat data.csv | parallel --header : -C ',' --tag curl -s -X POST http://localhost:8088/user/add -d \'{\"user_id\": {user_id}, \"user_name\":\"{user_name}\"}\' 復制代碼--pipe選項
有很多文本處理命令,并不從參數中獲取數據,而是從標準輸入中獲取,比如paste,通過指定--pipe選項,能將數據傳入到待執行命令的輸入流中去。
# 比如我想把data.csv變成data.json,且每3條數據聚合成一個json數組,如下: $ cat data.csv | parallel --header : -C ',' echo \'{\"user_id\": {user_id}, \"user_name\":\"{user_name}\"}\' | parallel -N3 --pipe paste -s -d, | sed -e 's/^/\[/' -e 's/$/]/' [{"user_id": 7, "user_name":"u7"},{"user_id": 8, "user_name":"u8"},{"user_id": 9, "user_name":"u9"}] [{"user_id": 1, "user_name":"u1"},{"user_id": 2, "user_name":"u2"},{"user_id": 3, "user_name":"u3"}] [{"user_id": 4, "user_name":"u4"},{"user_id": 5, "user_name":"u5"},{"user_id": 6, "user_name":"u6"}] [{"user_id": 10, "user_name":"u10"}] 復制代碼第一個parallel將每條數據變成了{"user_id": 1, "user_name":"u1"}形式。
第二個parallel將每3個json傳給paste的輸入流,然后paste使用逗號將它們連接起來。
每三個sed給首尾加上[],即成為了需要的數據格式。
與tmux結合使用
parallel提供了--tmuxpane,使得可以實現在tmux的多個panel中執行命令,這非常適合用來觀察一些監控命令的結果,比如查看每臺主機的網絡情況。
# 使用ping同時監控簡書、百度、知乎的網絡情況,注意,必須要加--delay選項 $ printf "www.jianshu.com\nwww.jianshu.com\nwww.baidu.com\nwww.zhihu.com"|parallel -j0 --delay 1 --tmuxpane ping {0} See output with: tmux -S /tmp/tmsOHGXM attach # 查看tmux面板 $ tmux -S /tmp/tmsOHGXM attach 復制代碼如下,為tmux面板的內容,你將能直觀的看到4臺機器的ping實時結果。
總結
如果你經常使用shell來幫助你處理各種問題,我想parallel命令就非常適合你,它真的太強大太方便了。
作者:打碼日記
總結
以上是生活随笔為你收集整理的好用的parallel命令的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: angular页面间传递参数
- 下一篇: BEC高级备考