以前在主產品用過一個運維同事寫的工具,devpssh。能夠經過指定主機列表來執行一條shell命令,而後獲取到全部的返回結果,輸出到屏幕上。nginx
我我的以爲這個工具很實用,尤爲是在有多臺Nginx服務器的時候,因爲負載均衡策略下,不一樣的請求可能會被下放到不一樣的get機,所以產生的日誌文件就可能分佈在多臺機器上。若是咱們一個個地到每臺get機上去執行shell語句。首先工做量會很大,另外獲取到的結果也不容易整理。而此時用一下devpssh,就沒有這些負擔了。算法
在正式介紹如何寫一個這樣的工具以前,先來看看須要哪些基礎的知識。shell
說到主機之間的信任,仍是要將歷史往前追溯一下。談談SSH。簡單來講SSH是一種網絡協議,用於計算機之間的加密登陸。之因此是加密登陸就是應爲原始的用戶遠程登陸是明文的,一旦被截獲,信息就泄露了。api
SSH是協議,具體有不少實現。有商業實現的,也有開源實現。不過大體來看,用法是一致的。bash
先來看看安裝了ssh的機器有什麼不一樣吧。 服務器
id_rsa是使用RSA算法獲得的私鑰 id_rsa.pub是對稱的RSA算法獲得的公鑰。 瞭解過對稱加密算法的應該都知道,妥善保存好私鑰是一件很重要的事情。網絡
通常來講,第一次使用ssh登陸到遠程主機的時候,會有以下提示信息:負載均衡
The authenticity of host 'host (12.18.429.21)' can't be established. RSA key fingerprint is 98:2e:d7:e0:de:9f:ac:67:28:c2:42:2d:37:16:58:4d. Are you sure you want to continue connecting (yes/no)? 複製代碼
這段話的大體意思是說,沒法確認你即將登陸的遠程主機的真實性,可是能夠了解的就只有它的公鑰指紋,若是肯定要進行鏈接,選擇yes便可。 而後會出現以下字樣:運維
Warning: Permanently added 'host,12.18.429.21' (RSA) to the list of known hosts.
複製代碼
而後ssh會提示你使用密碼進行登陸了。正確輸入密碼後,就能夠正常的登陸了。這個時候,其實遠程主機的公鑰就被保存到了~/.ssh/known_hosts文件中了。內容以下: ssh
其中每一行都表明了一個曾經成功鏈接過的遠程主機的公鑰信息。
可是每次遠程登陸都須要輸入一遍密碼,感受次數多了,老是感受有點麻煩。而ssh也支持使用公鑰進行登陸,這樣就省去了每次登錄都要輸入一遍密碼的步驟了。
具體的作法以下: 將本身的電腦的公鑰發送到目標主機的.ssh/authorized_keys中,這樣登陸的時候ssh協議經過對稱加密,解密的驗證過程,就能夠實現公鑰登陸了。
這個對稱加密,解密大體有這麼個流程。
最後來一個小總結:
公鑰免密登陸也會是待會主機間的信任的基礎。再來回顧下需求,我要在某一臺主機上執行一條命令,而後獲取所有的get機上相對應的內容。那麼這臺主機就能夠做爲master。
在master上,將經過ssh-keygen命令生成的公鑰發送到要進行遠程登陸的get機的.ssh/authenrized_keys中。 好比: master機器爲192.168.30.100 get機列表是: 192.168.32.102 192.168.32.105 192.168.32.109 192.168.32.110 咱們就能夠依次將100的公鑰使用SCP命令或者其餘的上傳工具,上傳到對應的get機的authenrized_keys文件中。
ssh-keygen -t rsa //此處一路回車,生成祕鑰
scp .ssh/id_rsa.pub 192.168.32.102:~/ //把祕鑰拷貝到其餘遠程機器
ssh 192.168.30.102 ‘cat id_rsa.pub >> .ssh/authorized_keys’ //(遠程執行命令)在遠程機器上生成認證文件
複製代碼
這樣,將master的公鑰就成功的添加到102這臺get機上了。其餘的get機就能夠按照一樣的方法作下處理。處理完以後,就可使用公鑰進行免密碼登陸到遠程主機了。
至此,主機間的信任就算結束了。
目標需求是獲取全部get機上執行的shell命令,並進行整合輸出。我在網上找了一個shell腳本,大體的內容以下:
#!/usr/bin bash
docommand()
{
hosts=`sed -n '/^[^#]/p' hostlist`
for host in $hosts
do
echo "" # 換個行
ssh $host "$@"
done
return 0
}
if [ $# -lt 1 ]
then
echo "$0 cmd"
exit
fi
docommand "$@"
複製代碼
而後須要在同級目錄下建立一個get主機列表。
192.168.32.102
192.168.32.105
192.168.32.109
192.168.32.110
複製代碼
而後懶得輸入bash前綴來執行命令的話,就能夠寫一個alias了在~/.bashrc 文件末尾添加以下內容:
alias devpssh='bash /home/developer/runcommand.sh'
複製代碼
而後**source ~/.bashrc*
這樣就能夠經過以下格式,來批量在主機之間執行shell命令了,具體的格式以下:
devpssh 'cat /var/log/nginx/api_acces.log | grep curuserid=2614677 | tail -1'
複製代碼
至此,在多臺主機之間執行shell命令也就得以實現了。
本次內容比較少,單純的瞭解了下ssh的一些相關知識點。而後是利用公鑰免密登陸並執行相關的shell命令。
麻雀雖小,可是卻很實用。