批量併發執行工具PDO,主要是解決批量執行的繁鎖,更安全便捷的操做工具.
自己是解決公司內部的一些問題,而且有不少特定環境的一些使用,如今抽離出其中均可以使用的部分.linux
先獲取依賴的第三方庫:git
go get github.com/cihub/seelog go get github.com/robfig/config
安裝go 環境.github
go build pdo.go
配置文件目錄,默認在~/.pdo.若是不在此處指定.web
獲取機器列表和相對應的路徑有三種途徑.(這裏去掉了數據庫這種特定的)redis
若是列表名稱是這樣的結構,xxx.yyy 那麼過濾的就是yyy,若是沒有這個須要,能夠忽略.數據庫
配置文件中:macos
[IDC] JX:yf01,cq01,dbl01,ai01 TC:cq02,tc,m1,db01
日誌主要記錄使用者,使用過的命令,保證多人操做的時候能夠查看到.centos
日誌配置文件查看github.com/cihub/seelog
主配置文件格式查看github.com/robfig/config緩存
會有主機和命令和單臺執行確認.安全
[PDO] logconf:/home/work/.pdo/log.xml [IDC] JX:yf01,cq01,dbl01,ai01,jx,cp01 TC:cq02,tc,m1,db01,st01 [TEMPLATE] container : /home/work/.pdo/template/container.sh startbykill : /home/work/.pdo/template/startbykill.sh [CMD] restart: bash bin/xxxControl.sh N%%N%%N%%restart findLog: find xxx00* -name "debug" -type d findCount: ls log | wc -l
第一列必定是host,hostname或者ip均可以,第二列可選是命令工做的路徑.
cat godir/1.list yf-xxx-app01.yf01 /home/work/xxx001 yf-xxx-app02.yf01 /home/work/xxx004 yf-xxx-app03.yf01 /home/work/xxx002
cat 1.list | pdo -r 2 "pwd" >>>> Welcome ajian... yf-xxx-pre01.vm -/home/work/xxx001 yf-xxx-app01.yf01 -/home/work/xxx001 yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app04.yf01 -/home/work/xxx001 1-xxx-app17.m1 -/home/work/xxx001 m1-xxx-app25.m1 -/home/work/xxx001 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 ai-xxx-app01.ai01 -/home/work/xxx004 db-xxx-app17.db01 -/home/work/xxx003 db-xxx-app63.db01 -/home/work/xxx001 #--Total--# 13 #---CMD---# pwd //每一次確認 Continue (y/n):y go on ... [1/13] yf-xxx-app01.yf01 [SUCCESS]. /home/work/xxx001 Continue (y/n):[1/13] yf-xxx-pre01.vm [SUCCESS]. /home/work/xxx001 //單臺執行完 第二次確認 Continue (y/n): //後面就是按2併發執行.
這個主要是解決一些重複執行的繁鎖的單行命令.看下面的一個重啓命令非常麻煩,但經過轉換以後就輸入很方便了.
-cmd爲縮寫命令= bash bin/xxxControl.sh N%%N%%N%%restart
$ pdo -f 1.list -cmd restart >>>> Welcome ajian... yf-xxx-app01.yf01 -/home/work/xxx001 yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app04.yf01 -/home/work/xxx001 yf-xxx-app00.yf01 -/home/work/xxx001 yf-xxx-app0148.yf01 -/home/work/xxx004 dbl-xxx-app0109.dbl01 -/home/work/xxx003 m1-xxx-app17.m1 -/home/work/xxx001 m1-xxx-app25.m1 -/home/work/xxx001 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 cq01-xxx-app0179.cq01 -/home/work/xxx001 cq01-xxx-app0131.cq01 -/home/work/xxx005 st01-xxx-app03.st01 -/home/work/xxx001 st01-xxx-app04.st01 -/home/work/xxx001 st01-xxx-app02.st01 -/home/work/xxx001 st01-xxx-app00.st01 -/home/work/xxx001 st01-xxx-app05.st01 -/home/work/xxx001 cq02-xxx-app0258.cq02 -/home/work/xxx001 cq02-xxx-app0287.cq02 -/home/work/xxx001 jx-xxx-app17.jx -/home/work/xxx001 ai-xxx-app10.ai01 -/home/work/xxx001 db-xxx-app17.db01 -/home/work/xxx003 #--Total--# 24 #---CMD---# bash bin/xxxControl.sh N%%N%%N%%restart Continue (y/n):
使用帶-o 指定輸出目錄,將不會再打印在屏幕上,主要是對grep日誌這種需求使用.速度要比屏幕打印快不少,是實時寫入.
$ cat 1.list | pdo -o xxxout "pwd" >>>> Welcome ajian... yf-xxx-app01.yf01 -/home/work/xxx001 yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app04.yf01 -/home/work/xxx001 yf-xxx-app00.yf01 -/home/work/xxx001 yf-xxx-app0148.yf01 -/home/work/xxx004 dbl-xxx-app0109.dbl01 -/home/work/xxx003 m1-xxx-app17.m1 -/home/work/xxx001 m1-xxx-app25.m1 -/home/work/xxx001 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 cq01-xxx-app0179.cq01 -/home/work/xxx001 cq01-xxx-app0131.cq01 -/home/work/xxx005 st01-xxx-app03.st01 -/home/work/xxx001 st01-xxx-app04.st01 -/home/work/xxx001 st01-xxx-app02.st01 -/home/work/xxx001 st01-xxx-app00.st01 -/home/work/xxx001 st01-xxx-app05.st01 -/home/work/xxx001 cq02-xxx-app0258.cq02 -/home/work/xxx001 cq02-xxx-app0287.cq02 -/home/work/xxx001 cq02-xxx-app0212.cq02 -/home/work/xxx001 jx-xxx-app17.jx -/home/work/xxx001 ai-xxx-app10.ai01 -/home/work/xxx001 db-xxx-app17.db01 -/home/work/xxx003 #--Total--# 25 #---CMD---# pwd Continue (y/n):y go on ... [1/25] yf-xxx-app01.yf01 [SUCCESS]. Continue (y/n):y go on ... [2/25] yf-xxx-app02.yf01 [SUCCESS]. [3/25] yf-xxx-app03.yf01 [SUCCESS]. [4/25] yf-xxx-app04.yf01 [SUCCESS]. [5/25] yf-xxx-app00.yf01 [SUCCESS]. [6/25] yf-xxx-app0148.yf01 [SUCCESS]. [7/25] dbl-xxx-app0109.dbl01 [SUCCESS]. [8/25] m1-xxx-app17.m1 [SUCCESS]. [9/25] m1-xxx-app25.m1 [SUCCESS]. [10/25] m1-xxx-app0220.m1 [SUCCESS]. [11/25] m1-xxx-app0154.m1 [SUCCESS]. [12/25] cq01-xxx-app0242.cq01 [SUCCESS]. [13/25] cq01-xxx-app0179.cq01 [SUCCESS]. [14/25] cq01-xxx-app0131.cq01 [SUCCESS]. [15/25] st01-xxx-app03.st01 [SUCCESS]. [16/25] st01-xxx-app04.st01 [SUCCESS]. [17/25] st01-xxx-app02.st01 [SUCCESS]. [18/25] st01-xxx-app00.st01 [SUCCESS]. [19/25] st01-xxx-app05.st01 [SUCCESS]. [20/25] cq02-xxx-app0258.cq02 [SUCCESS]. [21/25] cq02-xxx-app0287.cq02 [SUCCESS]. [22/25] cq02-xxx-app0212.cq02 [SUCCESS]. [23/25] jx-xxx-app17.jx [SUCCESS]. [24/25] ai-xxx-app10.ai01 [SUCCESS]. [25/25] db-xxx-app17.db01 [SUCCESS].
時間都帶單位,如1秒 1s , 1分鐘 1m , 1小時 1h .
這裏的1.log是一個大文件.
$ pdo -f 1.list -t 1s -o out/ -r 3 "cat 1.log" >>>> Welcome ajian... yf-xxx-app01.yf01 -/home/work/xxx001 yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app04.yf01 -/home/work/xxx001 yf-xxx-app00.yf01 -/home/work/xxx001 yf-xxx-app0148.yf01 -/home/work/xxx004 dbl-xxx-app0109.dbl01 -/home/work/xxx003 m1-xxx-app17.m1 -/home/work/xxx001 m1-xxx-app25.m1 -/home/work/xxx001 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 cq01-xxx-app0179.cq01 -/home/work/xxx001 cq01-xxx-app0131.cq01 -/home/work/xxx005 st01-xxx-app03.st01 -/home/work/xxx001 st01-xxx-app04.st01 -/home/work/xxx001 st01-xxx-app02.st01 -/home/work/xxx001 st01-xxx-app00.st01 -/home/work/xxx001 st01-xxx-app05.st01 -/home/work/xxx001 cq02-xxx-app0258.cq02 -/home/work/xxx001 cq02-xxx-app0287.cq02 -/home/work/xxx001 cq02-xxx-app0211.cq02 -/home/work/xxx001 cq02-xxx-app0212.cq02 -/home/work/xxx001 jx-xxx-app17.jx -/home/work/xxx001 ai-xxx-app10.ai01 -/home/work/xxx001 db-xxx-app17.db01 -/home/work/xxx003 #--Total--# 26 #---CMD---# cat log/ral-zoo.log Continue (y/n):y go on ... [1/26] yf-xxx-app01.yf01 [Time Over KILLED]. Continue (y/n):y go on ... [2/26] yf-xxx-app04.yf01 [Time Over KILLED]. [3/26] yf-xxx-app03.yf01 [Time Over KILLED]. [4/26] yf-xxx-app02.yf01 [Time Over KILLED]. [5/26] yf-xxx-app0148.yf01 [SUCCESS]. [6/26] dbl-xxx-app0109.dbl01 [SUCCESS]. [7/26] yf-xxx-app00.yf01 [Time Over KILLED]. [8/26] m1-xxx-app0220.m1 [SUCCESS]. [9/26] m1-xxx-app25.m1 [Time Over KILLED]. [10/26] m1-xxx-app17.m1 [Time Over KILLED]. [11/26] m1-xxx-app0154.m1 [SUCCESS]. [12/26] cq01-xxx-app0242.cq01 [SUCCESS]. [13/26] cq01-xxx-app0179.cq01 [Time Over KILLED]. [14/26] cq01-xxx-app0131.cq01 [SUCCESS]. [15/26] st01-xxx-app03.st01 [Time Over KILLED]. [16/26] st01-xxx-app04.st01 [Time Over KILLED]. [17/26] st01-xxx-app02.st01 [Time Over KILLED]. [18/26] st01-xxx-app00.st01 [Time Over KILLED]. [19/26] st01-xxx-app05.st01 [Time Over KILLED]. [20/26] cq02-xxx-app0211.cq02 [SUCCESS]. [21/26] cq02-xxx-app0258.cq02 [SUCCESS]. [22/26] cq02-xxx-app0287.cq02 [SUCCESS]. [23/26] ai-xxx-app10.ai01 [SUCCESS]. [24/26] cq02-xxx-app0212.cq02 [SUCCESS]. [25/26] jx-xxx-app17.jx [Time Over KILLED]. [26/26] db-xxx-app17.db01 [SUCCESS].
copy文件實際上是能夠copy目錄的,只要遠端的目錄是存在的就不會報錯.
$ cat 1.host | pdo -c get.sh /tmp/ >>>> Welcome ajian... yf-xxx-upload05.yf01 -/home/work yf-xxx-upload01.yf01 -/home/work yf-xxx-upload02.yf01 -/home/work #--Total--# 3 #---CMD---# get.sh --> /tmp/ Continue (y/n):y go on ... [1/3] yf-xxx-upload05.yf01 [SUCCESS]. Continue (y/n):y go on ... [2/3] yf-xxx-upload01.yf01 [SUCCESS]. [3/3] yf-xxx-upload02.yf01 [SUCCESS]. //檢查下文件 $ cat 1.host | pdo "ls /tmp/get.sh" >>>> Welcome ajian... yf-xxx-upload05.yf01 -/home/work yf-xxx-upload01.yf01 -/home/work yf-xxx-upload02.yf01 -/home/work #--Total--# 3 #---CMD---# ls /tmp/get.sh Continue (y/n):y go on ... [1/3] yf-xxx-upload05.yf01 [SUCCESS]. /tmp/get.sh Continue (y/n):y go on ... [2/3] yf-xxx-upload01.yf01 [SUCCESS]. /tmp/get.sh [3/3] yf-xxx-upload02.yf01 [SUCCESS]. /tmp/get.sh
-R 就是至關於第四種列表來源,當執行錯誤,或者ctrl+c的時候就可使用上,避免列表反覆執行某些命令.
此次多加兩臺服務器,有兩臺是沒有這個上面腳本文件的.因此新加的服務器會報錯.
$ cat 2.list | pdo "ls /tmp/get.sh" >>>> Welcome ajian... yf-xxx-upload05.yf01 -/home/work yf-xxx-upload01.yf01 -/home/work yf-xxx-upload02.yf01 -/home/work yf-xxx-upload03.yf01 -/home/work yf-xxx-upload04.yf01 -/home/work #--Total--# 5 #---CMD---# ls /tmp/get.sh Continue (y/n):y go on ... [1/5] yf-xxx-upload05.yf01 [SUCCESS]. /tmp/get.sh Continue (y/n):y go on ... [2/5] yf-xxx-upload01.yf01 [SUCCESS]. /tmp/get.sh [3/5] yf-xxx-upload02.yf01 [SUCCESS]. /tmp/get.sh [4/5] yf-xxx-upload03.yf01 [FAILED]. ls: /tmp/get.sh: No such file or directory [5/5] yf-xxx-upload04.yf01 [FAILED]. ls: /tmp/get.sh: No such file or directory //使用-R 就能夠直接拿到上一次執行失敗的列表. $pdo -R "ls /tmp/get.sh" >>>> Welcome ajian... yf-xxx-upload03.yf01 -/home/work yf-xxx-upload04.yf01 -/home/work #--Total--# 2 #---CMD---# ls /tmp/get.sh Continue (y/n):y go on ... [1/2] yf-xxx-upload03.yf01 [FAILED]. ls: /tmp/get.sh: No such file or directory //若是是使用的ctrl+C中斷了列表,-R會記錄未執行完(包括已經執行但失敗的列表) $ cat 1.host | pdo -T 10s "ls /tmp/get.sh" >>>> Welcome ajian... yf-xxx-upload05.yf01 -/home/work yf-xxx-upload01.yf01 -/home/work yf-xxx-upload02.yf01 -/home/work yf-xxx-upload03.yf01 -/home/work yf-xxx-upload04.yf01 -/home/work #--Total--# 5 #---CMD---# ls /tmp/get.sh Continue (y/n):y go on ... [1/5] yf-xxx-upload05.yf01 [SUCCESS]. /tmp/get.sh Continue (y/n):y go on ... [2/5] yf-xxx-upload01.yf01 [SUCCESS]. /tmp/get.sh ^C$ pdo -R "ls /tmp/get.sh" >>>> Welcome ajian... yf-xxx-upload02.yf01 -/home/work yf-xxx-upload03.yf01 -/home/work yf-xxx-upload04.yf01 -/home/work #--Total--# 3 #---CMD---# ls /tmp/get.sh Continue (y/n):y go on ... [1/3] yf-xxx-upload02.yf01 [SUCCESS]. /tmp/get.sh Continue (y/n):
### -e腳本執行功能
$ cat t.sh #!/bin/bash cd /tmp/ && pwd echo "test" touch /tmp/t.log $ cat 1.host | pdo -e t.sh >>>> Welcome ajian... yf-xxx-upload05.yf01 -/home/work yf-xxx-upload01.yf01 -/home/work yf-xxx-upload02.yf01 -/home/work #--Total--# 3 #---CMD---# Script: t.sh Continue (y/n):y go on ... [1/3] yf-xxx-upload05.yf01 [SUCCESS]. /tmp test
模板功能主要是解決重複的腳本修改動做,能夠固化成一些模板,直接使用.
配置中能夠本身添加模板
$ cat ~/.pdo/pdo.conf [TEMPLATE] container : /home/work/.pdo/template/container.sh
模板內容,這個模版主要是在一臺服務器上的xxxxxx目錄裏面進行操做. {{.CMD}} 就是會被替換的位置.
$ cat /home/work/.pdo/template/container.sh #!/bin/bash grep -l "^appName:" /home/work/xxx[0-9][0-9][0-9]/xxx.conf | while read file ; do eval $(awk '{if($1 ~ /xxxPath/){printf "apppath=%s\n",$2};if($1 ~ /appName/){printf "appName=%s",$2}}' $file) echo $appName if [ -d "$apppath" ];then cd $apppath {{.CMD}} fi done
使用嵌入命令
$ pdo -a xxxtest -temp container "pwd" >>>> Welcome ajian... yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app00.yf01 -/home/work/xxx001 yf-xxx-app0148.yf01 -/home/work/xxx004 dbl-xxx-app0109.dbl01 -/home/work/xxx003 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 cq01-xxx-app0179.cq01 -/home/work/xxx001 cq02-xxx-app0258.cq02 -/home/work/xxx001 cq02-xxx-app0287.cq02 -/home/work/xxx001 cq02-xxx-app0211.cq02 -/home/work/xxx001 jx-xxx-app17.jx -/home/work/xxx001 db-xxx-app17.db01 -/home/work/xxx003 #--Total--# 14 #---CMD---# pwd Continue (y/n):y go on ... [1/14] yf-xxx-app02.yf01 [SUCCESS]. xxxtest /home/work/xxx001 jingyan /home/work/xxx002 pc_anti /home/work/xxx003 bakan /home/work/xxx004 smallapp /home/work/xxx006 appui /home/work/xxx008 Continue (y/n):n exit ...
還能夠嵌入腳本
//腳本內容 $ cat 1.sh echo "1.sh" pwd //嵌入腳本使用-b $ pdo -a xxxtest -temp container -b 1.sh >>>> Welcome ajian... yf-xxx-app02.yf01 -/home/work/xxx001 yf-xxx-app03.yf01 -/home/work/xxx001 yf-xxx-app00.yf01 -/home/work/xxx001 yf-xxx-app0148.yf01 -/home/work/xxx004 dbl-xxx-app0109.dbl01 -/home/work/xxx003 m1-xxx-app0220.m1 -/home/work/xxx001 m1-xxx-app0154.m1 -/home/work/xxx004 cq01-xxx-app0242.cq01 -/home/work/xxx003 cq01-xxx-app0179.cq01 -/home/work/xxx001 cq02-xxx-app0258.cq02 -/home/work/xxx001 cq02-xxx-app0287.cq02 -/home/work/xxx001 cq02-xxx-app0211.cq02 -/home/work/xxx001 jx-xxx-app17.jx -/home/work/xxx001 db-xxx-app17.db01 -/home/work/xxx003 #--Total--# 14 #---CMD---# Continue (y/n):y go on ... [1/14] yf-xxx-app02.yf01 [SUCCESS]. xxxtest 1.sh /home/work/xxx001 jingyan 1.sh /home/work/xxx002 pc_anti 1.sh /home/work/xxx003 bakan 1.sh /home/work/xxx004 smallapp 1.sh /home/work/xxx006 appui 1.sh /home/work/xxx008
這個功能有兩種使用場景:
因此這種顯示方式取決於時間的前後順序,交錯輸出.
拿redis的遷移過程爲例子:
redis遷移至少有原來的一主一從,新主和新從.在遷移的過程當中須要同時觀察四臺服務器的變化.若是是每次ssh四臺服務器tail 日誌是很麻煩並且容易出錯.
如今使用pdo命令:
//操做的主機列表1.list tc-yyy-redis40.tc /home/yyy/redis-shard3 //old master cq02-yyy-redis80.cq02 /home/yyy/redis-shard3 //new master yf-yyy-redis40.yf01 /home/yyy/redis-shard3 //old slave jx-yyy-redis80.jx /home/yyy/redis-shard3 //new slave 第一步操做: yf-yyy-redis40.yf01爲主 --> cq02-yyy-redis80.cq02 #命令 #cat 1.list | pdo -r 5 -y -show row -match "success" "tail -f log/redis.log" > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:56:51 * Slave ask for new-synchronization //被要求同步 > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 13:56:58 * (non critical): Master does not understand REPLCONF listening-port: Reading from master: Connection timed out > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:56:58 * Slave ask for synchronization > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:56:58 * Starting BGSAVE for SYNC > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:56:58 * Background saving started by pid 22855 > yf-yyy-redis40.yf01 >> [22855] 06 Jan 13:58:31 * DB saved on disk //dump到磁盤 > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:58:31 * Background saving terminated with success > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 13:58:31 * MASTER <-> SLAVE sync: receiving 1868940396 bytes from master //從接收到主的文件 > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 13:58:47 * MASTER <-> SLAVE sync: Loading DB in memory //將接收到的文件加載到內存 > yf-yyy-redis40.yf01 >> [11523] 06 Jan 13:58:47 * Synchronization with slave succeeded //文件同步成功 > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 14:01:21 # Update masterstarttime[1382324097] after loading db > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 14:01:21 * AA: see masterstarttime: ip[10.36.114.56], port[9973], timestamp[1382324097] > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 14:01:21 * Write aof_global_offset[92961804447] to new aof_file[46] success > cq02-yyy-redis80.cq02 >> [14752] 06 Jan 14:01:21 * MASTER <-> SLAVE sync: Finished with success //slave完成主從同步,說明第一步已經結束.
說明:
如下是一個測試腳本:隨機打印數字 1.sh
#!/bin/bash for x in `seq 1 10` ; do echo $x sleep $[ ( $RANDOM % 4 ) + 1 ]s done //可使用以下命令: # cat 1.list | pdo -r 5 -y -show row -match "5" -e 1.sh
還有更多的組合哦.