天天看點

系統管理工具包: 使用 SSH 進行分布式管理

使用安全 Shell (SSH) 在遠端 UNIX® 系統中運作指令,并使用一些簡單的腳本構成一個系統,該系統允許您在一台計算機中同時管理許多系統,而無需直接登入到計算機本身。本文還介紹了分布式管理系統的基礎知識,以及使用該技術的某些腳本和解決方案。

關于本系列

典 型的 UNIX® 管理者擁有一套經常用于輔助管理過程的關鍵實用工具、訣竅和系統。存在各種用于簡化不同過程的關鍵實用工具、指令行鍊和腳本。其中一些工具來自于操作系 統,而大部分的訣竅則來源于長期的經驗積累和減輕系統管理者工作壓力的要求。本系列文章主要專注于最大限度地利用各種 UNIX 環境中可用的工具,包括簡化異構環境中的管理任務的方法。

系統管理工具包: 使用 SSH 進行分布式管理
系統管理工具包: 使用 SSH 進行分布式管理
系統管理工具包: 使用 SSH 進行分布式管理
請通路“系統管理者工具包”系列文章
系統管理工具包: 使用 SSH 進行分布式管理

對遠端登入進行簡化

安 全 Shell (SSH) 工具為遠端主機的登入和交換資訊提供了一種安全的方法。其中提供了大量不同的工具,包括通用的 SSH 工具(它提供了遠端終端連接配接)、SCP(一種安全的、主機到主機的、複制解決方案)和 SFTP(一種安全的檔案複制解決方案,采用了與标準 FTP 工具類似的工作方式)。

所有這些工具都是安全的,因為對交換的資訊進行了加密。此外,使用了公鑰或者私鑰機制確定連接配接的身份驗證的安全。SSH 的主要優點之一是,通過将您的公鑰複制到一台遠端計算機,您可以繞過正常的登入和密碼交換。

盡管使用 SSH 登入到遠端計算機是非常有用的(因為這樣做意味着您無需提供密碼),不過在執行遠端管理方面,它更有價值。如果必須輸入密碼,将使得無法實作遠端管理(例如,通過 cron 運作一個指令)的自動化,因為在自動化的腳本中,您無須輸入密碼!

如果不交換您的公鑰,那麼使用 SSH 在多台計算機中運作相應的指令時,您必須為每台計算機輸入您的密碼。

要完成這種設定,有一種快速而簡單的方法,即建立一個公鑰:

$ ssh-keygen -t rsa      

請按照螢幕 上的說明執行相應的操作,但是在提示設定密碼時,不要進行設定,因為您需要在每次輸入密碼時使用這個密鑰。這個操作将建立一個私鑰和一個公鑰檔案。現在您 隻需要追加 .ssh/id_rsa.pub 中公鑰檔案的内容即可,并将其追加到遠端主機的 .ssh/authorized_key 檔案和您在登入時希望使用的使用者。您需要将這個公鑰檔案的内容追加到您希望自動地進行登入的每台計算機。

運作遠端指令

您可以通過許多方式來運作遠端指令。

通過将您希望 SSH 運作的指令添加在登入或者主機資訊的後面,您可以運作單個遠端指令。例如,要擷取一台遠端主機的磁盤資訊,您可以使用下面清單 1 中的這個指令,并獲得相應的輸出結果。

清單 1. 通過 SSH 運作一個簡單的指令

$ ssh [email protected] df

Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda3             14544820   3611520  10194464  27% /
udev                    128044       564    127480   1% /dev
/dev/hdc1              1968872     50340   1818516   3% /var/tmp
/dev/hdc2              1968904   1482220    386668  80% /usr/portage
/dev/hdc3              1968904     35760   1833128   2% /home/build
shm                     128044         0    128044   0% /dev/shm      

請記住,如果您尚未與這台遠端主機交換您的公鑰,那麼清單 1 中的序列需要您輸入一個密碼。

通過使用分号隔開每個指令,然後将整個指令序列用引号引起來(以便能夠将其識别為單個參數),您還可以執行一系列的指令。

清單 2 中顯示了一個執行磁盤檢查和正常運作時間檢查的示例。

清單 2. 執行磁盤檢查和正常運作時間檢查

$ ssh [email protected] "df;uptime"
Filesystem           1K-blocks      Used Available Use% Mounted on
/dev/hda3             14544820   3611520  10194464  27% /
udev                    128044       564    127480   1% /dev
/dev/hdc1              1968872     50340   1818516   3% /var/tmp
/dev/hdc2              1968904   1488100    380788  80% /usr/portage
/dev/hdc3              1968904     35760   1833128   2% /home/build
shm                     128044         0    128044   0% /dev/shm
 14:31:27 up 12 min,  2 users,  load average: 0.01, 0.05, 0.06      

在這個操作中,您可以将希望執行的許多指令聯接成字元串。還可以進行篩選工作,例如使用 grep 或者其他工具,但是您需要確定将整個遠端指令表達式嵌入到引号中(請參見清單 3)。

清單 3. 使用 grep 進行篩選

$ ssh [email protected] "cat /var/log/messages|grep 'su\['"
Dec 17 18:05:37 localhost su[19218]: pam_authenticate: Permission denied
Dec 17 18:05:37 localhost su[19218]: FAILED su for root by mc
Dec 17 18:05:37 localhost su[19218]: - pts/1 mc:root
Dec 17 18:06:31 localhost su[19221]: pam_authenticate: Permission denied
Dec 17 18:06:31 localhost su[19221]: FAILED su for root by mc
Dec 17 18:06:31 localhost su[19221]: - pts/1 mc:root
Dec 17 18:06:40 localhost su[19222]: pam_authenticate: Permission denied
Dec 17 18:06:40 localhost su[19222]: FAILED su for root by mc
...      

關于清單 3,需要說明的第一項内容是,您作為 root 使用者直接登入到遠端計算機。這是因為您希望檢視隻有超級使用者才能夠通路的檔案。您必須確定對您的系統進行相應的配置,以允許遠端 root 登入執行這樣的操作。

關于這個示例,第二項需要說明的重要内容是,您以遠端的方式執行了 grep 操作。實際上,您并不需要這樣做。已經将遠端主機的标準輸入和輸出複制到了本地計算機,是以可以在本地對該指令的輸出進行篩選,如清單 4 中所示。

清單 4. 在本地對輸出進行篩選

$ ssh [email protected] "cat /var/log/messages" | grep 'su\[' 
Dec 17 18:05:37 localhost su[19218]: pam_authenticate: Permission denied
Dec 17 18:05:37 localhost su[19218]: FAILED su for root by mc
Dec 17 18:05:37 localhost su[19218]: - pts/1 mc:root
Dec 17 18:06:31 localhost su[19221]: pam_authenticate: Permission denied
Dec 17 18:06:31 localhost su[19221]: FAILED su for root by mc
Dec 17 18:06:31 localhost su[19221]: - pts/1 mc:root
Dec 17 18:06:40 localhost su[19222]: pam_authenticate: Permission denied
Dec 17 18:06:40 localhost su[19222]: FAILED su for root by mc
Dec 17 18:06:40 localhost su[19222]: - pts/1 mc:root      

當然,其效果基本上是相同的。

當您希望通過管道進行傳輸的資訊或者指令是遠端的,那麼使用遠端管道方法是非常有用的。例如,使用清單 5 中的指令,您可以将

ls

du

組合使用,以确定不同目錄的磁盤使用情況。

清單 5. 确定不同指令的磁盤使用情況

ssh [email protected] "ls -d /usr/local/* |xargs du -sh "
Password: 
4.0K    /usr/local/bin
4.0K    /usr/local/games
4.0K    /usr/local/lib
0       /usr/local/man
4.0K    /usr/local/sbin
12K     /usr/local/share
4.0K    /usr/local/src      

在繼續将這些技術重新分布到多台計算機之前,這裡将介紹一個直接運作遠端互動會話的技巧,而無需首先進行登入。

直接的互動會話

如前所述,您可以直接運作許多不同的指令和指令鍊。SSH 解決方案的優點之一是,盡管指令本身是以遠端的方式執行的,但是指令的輸入和輸出都來源于調用的計算機。您可以将它作為一種在兩台計算機(與您希望執行的指令相關)之間交換資訊的方法。

您可以執行各種各樣不同的指令。然而,因為您直接從指令行運作這些指令,是以對于直接使用該方法所能執行的操作,通常是有限制的。例如,使用上面介紹的這種方法和技術,嘗試使用某種編輯器來編輯一個遠端檔案,通常都會失敗(請參見清單 6)。

清單 6. 編輯一個遠端檔案失敗

$ ssh [email protected] "emacs /etc/amavisd.conf"
emacs: standard input is not a tty      

通過強制 SSH 配置設定一個僞 tty 裝置(以便您可以直接與遠端應用程式進行互動),就可以解決這個問題。

在多台計算機中運作遠端的指令

到目前為止,您主要關注于在一台遠端計算機中運作單個的指令或者指令字元串。盡管在直接使用 SSH 執行遠端管理時,互動會話技巧非常有用,但是您可能希望實作這個過程的自動化,這意味着互動的組成部分未必非常有用。

要在多台計算機中以遠端的方式運作相同的指令,您需要為 SSH 指令和遠端指令(您希望運作的遠端指令,以便在每台遠端計算機上重複該過程)建構一個簡單的包裝。

您可以使用一個非常簡單的

for

循環來完成這項任務,如下面的清單 7 所示。

清單 7. 用于以遠端的方式運作指令的

for

循環

for remote in [email protected] mc@redhat; do echo $remote; ssh $remote 'df -h'; done
[email protected]
Filesystem            Size  Used Avail Use% Mounted on
/dev/hda3              14G  4.1G  9.2G  31% /
udev                  126M  564K  125M   1% /dev
/dev/hdc1             1.9G   56M  1.8G   4% /var/tmp
/dev/hdc2             1.9G  1.3G  558M  70% /usr/portage
/dev/hdc3             1.9G   35M  1.8G   2% /home/build
shm                   126M     0  126M   0% /dev/shm
mc@redhat
Filesystem            Size  Used Avail Use% Mounted on
/dev/mapper/VolGroup00-LogVol00
                      7.1G  5.5G  1.3G  82% /
/dev/hda1              99M   13M   82M  14% /boot
none                  125M     0  125M   0% /dev/shm      

您可以很容易地将其轉換為一個簡單腳本,如清單 8 所示。

清單 8. 将

for

循環簡化為簡單的指令

#!/bin/bash

# Script to run a command across multiple machines

# Global options

TIMEOUT=10
ERRLOG=/tmp/remote-err-$$.log
OUTLOG=/tmp/remote-out-$$.log

# Extract the command line

MACHINES=$1;shift
COMMAND=$1;shift

for machine in $MACHINES
do
    echo $machine
    ssh -oConnectTimeout=$TIMEOUT $machine $COMMAND >>$OUTLOG 2 >>$ERRLOG

done

cat $OUTLOG
cat $ERRLOG >&2
rm -f $OUTLOG $ERRLOG      

MACHINES 和 COMMAND 是從指令行中“按原樣”提取的内容。在使用這個腳本時,您必須将使用者或者主機組合和指令放到雙引号中,以確定能夠将其識别為單個參數。

唯一的其他附加内容是

TIMEOUT

選項。它為 SSH 設定了

ConnectTimout

選項,使得在運作一個指令時,您需要等待連接配接到一台不可用的主機。在這個腳本的開頭設定了預設值,應該可以確定您不會等待太久。

在 運作這個指令時,您将輸出發送到兩個日志檔案,一個用于标準輸出,另一個用于标準錯誤。然後,您将這些内容分别輸出到合适的位置。這是 SSH 的一個突出的優點,遠端計算機重定向到相同的位置(标準輸出、标準錯誤),是以您可以在本地進行重定向,同時保持輸出結果的含義。

例如,您可以使用這個腳本重複進行 df 檢查:

$ runremote.sh "gentoo redhat" "df -h"      

因為您對标準輸出和錯誤進行了重定向,是以您甚至可以為整個過程生成日志:

$ runremote.sh "gentoo redhat" "df -h" 2>/tmp/error.log      

使用遠端執行進行性能監視

在 使用 runremote.sh 時,您可能希望使用逾時值的确切值,并且您甚至可能希望更改這個值,這取決于您所執行的操作。例如,如果您正使用這個腳本通過在多台計算機中執行 uptime 指令來獲得目前狀态的快照,那麼您一定不希望為連接配接和指令的執行而等待太久,否則快照就會不精确。

另外,這個腳本實際上是按順序運作該指令。如果有大量的計算機,這種方式不僅很費時間,而且執行所選指令的第一台和最後一台計算機之間的時間延遲可能非常明顯,以至于無法互相關聯這些計算機。

對這個腳本稍作修改可得到 runremote2.sh,如清單 9 所示。這樣可以幾乎同時地執行這個遠端指令(通過在背景運作它),然後同樣通過管道将輸出傳輸到各自的日志檔案。

清單 9. 幾乎同時執行遠端指令的腳本

#!/bin/bash

# Script to run a command across multiple machines

# Global options

TIMEOUT=10
ERRLOG=/tmp/remote-err-$$.log
OUTLOG=/tmp/remote-out-$$.log

# Extract the command line

MACHINES=$1;shift
COMMAND=$1;shift

for machine in $MACHINES
do
    echo $machine >>$OUTLOG.$machine
    ssh -oConnectTimeout=$TIMEOUT $machine $COMMAND >>$OUTLOG.$machine
 2>>$ERRLOG.$machine &
done

# Wait for children to finish

wait

cat $OUTLOG.*
cat $ERRLOG.* >&2
rm -f $OUTLOG.* $ERRLOG.*      

在這個腳本中,您還将計算機名回顯到指令日志(對所提供的每台計算機來說是唯一的)。要確定該腳本不會在執行所有的遠端指令之前退出,您需要添加一個

wait

指令,以等待該腳本的所有子操作執行結束。

現在您可以使用該腳本同時檢查多台計算機(請參見清單 10)。

清單 10. 使用這個腳本同時檢查多台計算機

$ runremote2.sh "narcissus gentoo.vm droopy@nostromo mcbrown@nautilus" 'uptime'
droopy@nostromo
19:15  up 9 days, 23:42, 1 user, load averages: 0.01 0.03 0.00
gentoo.vm
 18:10:23 up 1 day, 10:02,  2 users,  load average: 1.72, 1.84, 1.79
mcbrown@nautilus
19:15  up 10:08, 4 users, load averages: 0.40 0.37 0.29
narcissus
19:15  up 8 days,  7:04, 4 users, load averages: 0.53 0.54 0.57      

當您希望獲得網絡的整體運作情況時,這種監視工作可能是非常有價值的,例如,要檢查運作 Web 或者資料庫服務的一組或者計算機叢集中的問題,并希望同時為該組中的多台計算機确定潛在的峰值或者問題。

然而請注意,其中仍然存在一定的延遲,尤其是在某台計算機特别繁忙的情況下,在不同的計算機中建立連接配接和執行指令所需的時間可能會産生非常明顯的時間延遲。

在多台計算機上運作相同的操作

在 大量的計算機中建立使用者可能是一件非常辛苦的工作。很顯然,有許多解決方案可用于解決使用單點登入實用工具所帶來的困難,如 Network Information Service (NIS) 或者基于 LDAP 的解決方案,但是您并不是必須使用這種方式對使用者進行同步。

您可以使用 SSH 在多台計算機上運作

adduser

指令,以完成這項任務。但是在 Solaris 中,該指令的名稱是

useradd

。指令行選項基本上是相同的,是以您可以兩次使用 run-remote.sh(請參見清單 11)。

清單 11. 運作 run-remote.sh 兩次

$ runremote.sh "gentoo redhat" "adduser -u 1000 -G sales,marketing mcbrown"
$ runremote.sh "solaris solaris-x86" "useradd -u 1000 -G sales,marketing mcbrown"      

現在,您已經在大量的計算機中使用相同的組和相同的使用者 ID 建立了相同的使用者,但是這樣做并不實用。

$ runremote.sh "gentoo solaris" "adduser.sh -u 1000 -G sales,marketing mcbrown"      

繼續閱讀