假設一種情境,需要在多個節點需要執行相同命令(考慮命令的不確定性),一般使用for 迴圈,ssh直接調用。例:需要查看每個節點的根目錄使用方式:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1HT535K-0.jpg" title="ssh-for.jpg" />
實際上,僅僅需將上述幾行命令寫成一個指令碼,將要執行的命令設為位置參數,即可在一個互信的叢集內滿足這些要求了,看似問題得到瞭解決,筆者此前也的確是這麼做的,但是問題出現了,有些命令的執行過程漫長,而這種按順序執行的方法,在執行有些命令時,等待的時間絕對是讓人崩潰的,譬如:如果在成百上千個節點叢集內,為每個節點更新庫(yum update),或者產生yum緩衝(yum makecache),或者每個節點都是新的,裡面有好多磁碟需要格式化掛載,如果使用for迴圈按順序執行,相信我,格式化的磁碟的等待時間會讓你無法忍受的,如果這個任務還是在規定的時間必須完成的話.......
好吧,囉嗦半天,需求出現了,先思考要解決的問題,後有簡單的部分實現和測試
1、所有節點是互信的,通過安裝系統時實現系統安裝階段實現)
2、所有節點可以使用常規的Regex取出對應的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/bashCMD=${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/screenLIST=(`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/bashDate="/bin/date +%k:%M:%S/%Y-%m-%d"Mlog=/var/log/mon.logTEE(){ /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 1done
在控制節點執行指令碼,結果如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1HT55J2-1.jpg" title="QQ圖片20130723170944.jpg" />
在三個節點看到任務啟動時間如下:
650) this.width=650;" src="http://www.bkjia.com/uploads/allimg/131227/1HT51R9-2.jpg" title="2013-07-23_171148.jpg" />
寫文不易,列位看官若覺得還能湊合,給好評哦,親..
剛弄完這個,忽然想到這個東西放後台應該也是可以的,經測試的確可以,因此,代碼可改為:
#!/bin/bashCMD=${1:-/usr/bin/yum makecache}DATE="/bin/date +%k:%M:%S/%Y-%m-%d"LOG=/var/log/ctrl.logSSH="/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