獲取多臺主機命令執行結果

菩提樹下的煮茶小童子發表於2017-12-05

在多臺主機之間批量執行shell語句的效果

之前在主產品用過一個運維同事寫的工具,devpssh。可以通過指定主機列表來執行一條shell命令,然後獲取到所有的返回結果,輸出到螢幕上。

我個人覺得這個工具很實用,尤其是在有多臺Nginx伺服器的時候,由於負載均衡策略下,不同的請求可能會被下放到不同的get機,因此產生的日誌檔案就可能分佈在多臺機器上。如果我們一個個地到每臺get機上去執行shell語句。首先工作量會很大,另外獲取到的結果也不容易整理。而此時用一下devpssh,就沒有這些負擔了。

在正式介紹如何寫一個這樣的工具之前,先來看看需要哪些基礎的知識。

  • 主機間信任
  • shell指令碼

主機間信任

說到主機之間的信任,還是要將歷史往前追溯一下。談談SSH。簡單來說SSH是一種網路協議,用於計算機之間的加密登入。之所以是加密登入就是應為原始的使用者遠端登入是明文的,一旦被截獲,資訊就洩露了。

SSH是協議,具體有很多實現。有商業實現的,也有開源實現。不過大致來看,用法是一致的。

先來看看安裝了ssh的機器有什麼不同吧。

執行過ssh-keygen後

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檔案中了。內容如下:

known_hosts檔案內容

其中每一行都代表了一個曾經成功連線過的遠端主機的公鑰資訊。

但是每次遠端登入都需要輸入一遍密碼,感覺次數多了,總是感覺有點麻煩。而ssh也支援使用公鑰進行登入,這樣就省去了每次登陸都要輸入一遍密碼的步驟了。

具體的做法如下: 將自己的電腦的公鑰傳送到目標主機的.ssh/authorized_keys中,這樣登入的時候ssh協議通過對稱加密,解密的驗證過程,就可以實現公鑰登入了。

這個對稱加密,解密大致有這麼個流程。

  • 本地主機使用ssh進行遠端登入
  • 遠端主機藉助authorized_keys裡面本地主機的資訊生成一個隨機字串發給本地主機
  • 本地主機用自己的私鑰將這個字串進行加密,發給遠端主機。
  • 遠端主機使用本地主機的公鑰進行 解密,如果成功,身份驗證也就通過了。

最後來一個小總結:

  • known_hosts裡面是已經成功遠端登入過的主機的公鑰資訊。
  • authenrized_keys是已經授權的,可以免密碼登入到本機的“主機”的公鑰資訊。

公鑰免密登入也會是待會主機間的信任的基礎。再來回顧下需求,我要在某一臺主機上執行一條命令,然後獲取全部的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機就可以按照同樣的方法做下處理。處理完之後,就可以使用公鑰進行免密碼登入到遠端主機了。

至此,主機間的信任就算結束了。


shell指令碼編寫

目標需求是獲取所有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語句的效果

至此,在多臺主機之間執行shell命令也就得以實現了。


總結

本次內容比較少,單純的瞭解了下ssh的一些相關知識點。然後是利用公鑰免密登入並執行相關的shell命令。

麻雀雖小,但是卻很實用。

相關文章