最近IDC上架了一批hadoop大數據業務服務器,由於集群環境需要在這些服務器之間實現ssh無密碼登錄的相互信任關系。具體的實現思路:在其中的任一台服務器上通過"ssh-keygen -t rsa"產生公私鑰文件,然后將公鑰文件拷貝成authorized_keys文件,最后將它的.ssh目錄下的文件全部批量拷貝到其他服務器的/root/.ssh目錄(即當前用戶家目錄的.ssh)下即可。這批hadoop服務器的ssh端口默認都是22,密碼默認都是kevin123456,ip列表如下:
192.168.10.202 192.168.10.203 192.168.10.205 192.168.10.206 192.168.10.207 192.168.10.208
注意:批量部署信任關系后,目標機器的authorized_keys文件不會被覆蓋,只會追加,所以如果目標機器之前做了別的信任關系,在新的信任關系做好后,老的信任關系不會丟失。
方法一: 適用於機器數量不多情況 [不推薦,也不安全]
首先在其中任一台服務器,如192.168.10.202上生產公私鑰文件: [root@server-202 ~]# ssh-keygen -t rsa [root@server-202 ~]# ls /root/.ssh/ id_rsa id_rsa.pub [root@server-202 ~]# chmod 600 /root/.ssh/id_rsa #一定要保證私鑰id_rsa文件權限是600! [root@server-202 ~]# cp /root/.ssh/id_rsa.pub /root/.ssh/authorized_keys [root@server-202 ~]# ls /root/.ssh/ authorized_keys id_rsa id_rsa.pub [root@server-202 ~]# vim /root/hosts 192.168.10.202 192.168.10.203 192.168.10.205 192.168.10.206 192.168.10.207 192.168.10.208 [root@server-202 ~]# for i in `cat /root/hosts`;do rsync -e "ssh -p22" -avpgolr /root/.ssh root@$i:/root/;done 執行該命令后,需要多次手動輸入密碼 執行后,這些機器之間就可以通過ssh密碼登錄了,即實現了相互信任關系。檢查下這些機器的/root/.ssh目錄,發現他們的公私鑰文件都是192.168.10.202這台機器的。 該種方法僅適用於少數服務器的情況,因為涉及到中途人工交互(輸入密碼等),如果服務器數量眾多的情況下,適用這種方式就比較傻X了,這就需要用到下面這種方法。
方法二: 使用expect批量做ssh信任
expect是交互性很強的腳本語言,可以幫助運維人員實現批量管理成千上百台服務器操作,是一款很實用的批量部署工具!expect依賴於tcl,而linux系統里一般不自帶安裝tcl,所以需要手動安裝。選擇其中的任意一台服務器上操作,比如這里還是選擇192.168.10.202這台機器。expect-5.43.0.tar和tcl8.4.11-src.tar 的下載地址:https://pan.baidu.com/s/1kVyeLt9 提取密碼:af9p
將expect和tcl的軟件包下載放到/usr/local/src目錄下,解壓tcl,進入tcl解壓目錄,然后進入unix目錄進行編譯安裝
[root@server-202 ~]# cd /usr/local/src/
[root@server-202 src]# tar -zvxf tcl8.4.11-src.tar.gz
[root@server-202 src]# cd tcl8.4.11/unix
[root@server-202 unix]# ./configure
[root@server-202 unix]# make && make install
安裝expect
[root@server-202 src]# tar -zvxf expect-5.43.0.tar.gz
[root@server-202 src]# cd expect-5.43.0
[root@server-202 expect-5.43.0]# ./configure --with-tclinclude=/usr/local/src/tcl8.4.11/generic --with-tclconfig=/usr/local/lib/
[root@server-202 expect-5.43.0]# make && make install
安裝完成后進行測試
[root@server-202 ~]# expect
expect1.1>
[root@server-202 ~]# which expect
/usr/local/bin/expect
做個expect執行文件的軟件
[root@server-202 ~]# ln -s /usr/local/bin/expect /usr/bin/expect
[root@server-202 ~]# ll /usr/bin/expect
批量實現信任關系的腳本如下:
[root@server-202 ~]# vim /opt/ssh_auth.sh
#!/bin/sh
DEST_USER=$1
PASSWORD=$2
HOSTS_FILE=$3
if [ $# -ne 3 ]; then
echo "Usage:"
echo "$0 remoteUser remotePassword hostsFile"
exit 1
fi
SSH_DIR=~/.ssh
SCRIPT_PREFIX=./tmp
echo ===========================
# 1. prepare directory .ssh
mkdir $SSH_DIR
chmod 700 $SSH_DIR
# 2. generat ssh key
TMP_SCRIPT=$SCRIPT_PREFIX.sh
echo "#!/usr/bin/expect">$TMP_SCRIPT
echo "spawn ssh-keygen -b 1024 -t rsa">>$TMP_SCRIPT
echo "expect *key*">>$TMP_SCRIPT
echo "send \r">>$TMP_SCRIPT
if [ -f $SSH_DIR/id_rsa ]; then
echo "expect *verwrite*">>$TMP_SCRIPT
echo "send y\r">>$TMP_SCRIPT
fi
echo "expect *passphrase*">>$TMP_SCRIPT
echo "send \r">>$TMP_SCRIPT
echo "expect *again:">>$TMP_SCRIPT
echo "send \r">>$TMP_SCRIPT
echo "interact">>$TMP_SCRIPT
chmod +x $TMP_SCRIPT
/usr/bin/expect $TMP_SCRIPT
rm $TMP_SCRIPT
# 3. generat file authorized_keys
cat $SSH_DIR/id_rsa.pub>>$SSH_DIR/authorized_keys
# 4. chmod 600 for file authorized_keys
chmod 600 $SSH_DIR/authorized_keys
echo ===========================
# 5. copy all files to other hosts
for ip in $(cat $HOSTS_FILE)
do
if [ "x$ip" != "x" ]; then
echo -------------------------
TMP_SCRIPT=${SCRIPT_PREFIX}.$ip.sh
# check known_hosts
val=`ssh-keygen -F $ip`
if [ "x$val" == "x" ]; then
echo "$ip not in $SSH_DIR/known_hosts, need to add"
val=`ssh-keyscan $ip 2>/dev/null`
if [ "x$val" == "x" ]; then
echo "ssh-keyscan $ip failed!"
else
echo $val>>$SSH_DIR/known_hosts
fi
fi
echo "copy $SSH_DIR to $ip"
echo "#!/usr/bin/expect">$TMP_SCRIPT
echo "spawn scp -r $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
echo "expect *assword*">>$TMP_SCRIPT
echo "send $PASSWORD\r">>$TMP_SCRIPT
echo "interact">>$TMP_SCRIPT
chmod +x $TMP_SCRIPT
#echo "/usr/bin/expect $TMP_SCRIPT" >$TMP_SCRIPT.do
#sh $TMP_SCRIPT.do&
/usr/bin/expect $TMP_SCRIPT
rm $TMP_SCRIPT
echo "copy done."
fi
done
echo done.
在上面腳本文件的同目錄下新建名為host的文件,將要建立ssh互信的機器名或ip地址添加到該文件中,每個機器名或ip占一行,如:
[root@server-202 ~]# vim /opt/host
192.168.10.202
192.168.10.203
192.168.10.205
192.168.10.206
192.168.10.207
192.168.10.208
最后就可以運行這個腳本ssh_auth.sh文件,ssh_auth.sh接受三個參數,遠程機器用戶名、密碼和host文件名(相對路徑或絕對路徑均可)。
[root@server-202 ~]# sh /opt/ssh_auth.sh root kevin123456 /opt/host
然后查看下其他服務器,發現.ssh目錄下的文件和192.168.10.202機器的.ssh目錄下的文件一致。
最后就可以在這些機器之間進行相互信任的ssh無密碼跳轉登錄了!
==========================================================================
注意:上面腳本針對的是服務器ssh端口是22的情況,如果ssh是非22端口,比如是22222端口。
則只需要在ssh_auth.sh腳本中修改下面兩行內容:
[root@server-202 ~]# cp /opt/ssh_auth.sh /opt/ssh_auth.sh.bak
[root@server-202 ~]# vim /opt/ssh_auth.sh #注意下面一個小寫p,一個大寫P
.......
val=`ssh-keyscan $ip 2>/dev/null`
修改為
val=`ssh-keyscan -p 22222 $ip 2>/dev/null`
.......
echo "spawn scp -r $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
修改為
echo "spawn scp -P 22222 -r $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
[root@server-202 ~]# diff /opt/ssh_auth.sh /opt/ssh_auth.sh.bak
57c57
< val=`ssh-keyscan -p 22222 $ip 2>/dev/null`
---
> val=`ssh-keyscan $ip 2>/dev/null`
67c67
< echo "spawn scp -P 22222 -r $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
---
> echo "spawn scp -r $SSH_DIR $DEST_USER@$ip:~/">>$TMP_SCRIPT
最后執行腳本,進行相互信任關系批量部署即可
[root@server-202 ~]# sh /opt/ssh_auth.sh root kevin123456 /opt/host
方式三: 使用Ansible批量做ssh信任 [推薦這種方式]
