假設一種場景,需要在多個節點需要執行相同命令(考慮命令的不確定性),一般使用for 循環,ssh直接調用。例:需要查看每個節點的根目錄使用情況:
實際上,僅僅需將上述幾行命令寫成一個腳本,將要執行的命令設為位置參數,即可在一個互信的集群內滿足這些要求了,看似問題得到了解決,筆者此前也的確是這麼做的,但是問題出現了,有些命令的執行過程漫長,而這種按順序執行的方法,在執行有些命令時,等待的時間絕對是讓人崩潰的,譬如:如果在成百上千個節點集群內,為每個節點更新庫(yum update),或者生成yum緩存(yum makecache),或者每個節點都是新的,裡面有好多磁盤需要格式化掛載,如果使用for循環按順序執行,相信我,格式化的磁盤的等待時間會讓你無法忍受的,如果這個任務還是在規定的時間必須完成的話.......
好吧,啰嗦半天,需求出現了,先思考要解決的問題,後有簡單的部分實現和測試
1、所有節點是互信的,通過安裝系統時實現(系統安裝階段實現)
2、所有節點可以使用常規的正則表達式取出對應的IP列表(腳本實現)
3、必須已安裝screen包,通過調用這個命令實現近乎並發執行任務(腳本實現)
4、命令執行結果的返回值獲取,用以判斷是否成功執行(未實現)
5、screen的資源釋放問題(未實現)
6、考慮網絡故障的錯誤處理(未實現)
7、考慮執行失敗的錯誤處理(未實現)
8、如果需要在每個節點執行的任務過多,可考慮將需要執行的任務寫成一個簡單的執行腳本,做推送,並控制執行;4、5、6、7的實現可考慮此方法。
9、考慮遠程執行命令時環境變量的問題(未實現)
10、不足之處,歡迎補充:
代碼部分實現如下:
代碼環境如下:
系統為CentOS6.3 x86_64 均已安裝screen包和互信
在互信的節點將命令:yum makecache 分別在如下三個節點執行:
10.1.6.1 disk1.mos.com disk1
10.1.6.2 disk2.mos.com disk2
10.1.6.3 disk3.mos.com disk3
#!/bin/bash CMD=${1:-/usr/bin/yum makecache} CMD_SN="disk_ver.1" DATE="/bin/date +%k:%M:%S/%Y-%m-%d" SSH="/usr/bin/ssh -q -o StrictHostKeyChecking=no" SCREEN=/usr/bin/screen LIST=(`cat /etc/hosts|grep mos.com|awk '{print $1}'`) for i in ${LIST[@]};do $SSH $i $SCREEN -dmS $CMD_SN $SSH $i $SCREEN -S $CMD_SN -X screen $CMD echo -en "`$DATE` $i done.\n\n" done
 
在三個節點分別放置一個簡單的腳本,用來查看命令是否被成功執行,代碼如下:
#!/bin/bash Date="/bin/date +%k:%M:%S/%Y-%m-%d" Mlog=/var/log/mon.log TEE(){ /usr/bin/tee -a $Mlog } while :;do INFO=`ps aux|grep -v grep|grep yum` if [ -n "$INFO" ];then echo -en "`$Date` : $INFO \n\n" |TEE fi sleep 1 done
在控制節點執行腳本,結果如下:
在三個節點看到任務啟動時間如下:
寫文不易,列位看官若覺得還能湊合,給好評哦,親..
剛弄完這個,忽然想到這個東西放後台應該也是可以的,經測試的確可以,因此,代碼可改為:
#!/bin/bash CMD=${1:-/usr/bin/yum makecache} DATE="/bin/date +%k:%M:%S/%Y-%m-%d" LOG=/var/log/ctrl.log SSH="/usr/bin/ssh -q -o StrictHostKeyChecking=no" LIST=(`cat /etc/hosts|grep mos.com|awk '{print $1}'`) for i in ${LIST[@]};do $SSH $i $CMD &>> $LOG & echo -en "`$DATE` $i done.\n\n" done
記錄所有輸出至日志文件,通過日志可判斷執行結果對錯。這樣一來,上述幾條中的第4、7都可完成,第5條的問題也不存在,僅剩第6和9兩條的需再做思考
本文出自 “自強不息” 博客,請務必保留此出處http://mos1989.blog.51cto.com/4226977/1255884