Expect 一键初始化部署批量分发服务器及客户端


:Mr.zhou  阅读: 3,227 次

  刚接触 expect ,花了一天的时间来研究。此文仅作测试学习用。也许有很多不严谨之处,望指正,谢谢。

一共使用了三个脚本:  distribute.sh 调用执行 distribute_sshkeygen.exp 和 distribute_client.exp。实现一键初始化全网批量分发环境。因为使用了 expect 脚本所以要在批量分发服务器上安装 expect 软件包。

  一键初始化部署做了以下动作:

  1、在批量分发服务器和分发客户端创建分发用的普通账户。

  2、为批量分发服务器的分发账户生成 SSH 密钥对。

  3、将批量分发服务器分发账户生成的 SSH 公钥,发给所有客户端的分发账户。实现远程 SSH 分发账户免密码登录。

  4、批量分发使用 scp ssh sudo cp 实现。所以要为各客户端的分发账户用 sudo 对 cp 进行授权。

  5、最终模拟分发场景对部署是否成功进行检验。

  一、演示环境:

  NFS服务器兼批量分发服务器:

[root@nfs-server ~]# uname -nr&&ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
nfs-server.z-dig.com 2.6.32-504.el6.x86_64
172.16.1.100
[root@nfs-server ~]#

  备份服务器 批量分发客户端:

[root@backup-server ~]# uname -nr&&ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
backup-server.z-dig.com 2.6.32-504.el6.x86_64
172.16.1.101
[root@backup-server ~]# 

  Lnmp 服务器 批量分发客户端:

[root@lnmp-1 ~]# uname -nr&&ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'                        
lnmp-1.z-dig.com 2.6.32-504.el6.x86_64
172.16.1.10
[root@lnmp-1 ~]# 

  Lamp 服务器 批量分发客户端:

[root@lamp-1 ~]# uname -nr&&ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
lamp-1.z-dig.com 2.6.32-504.el6.x86_64
172.16.1.20
[root@lamp-1 ~]# 

  DB 服务器 批量分发客户端:

[root@db-server ~]# uname -nr&&ifconfig eth0|awk -F "[ :]+" 'NR==2{print $4}'
db-server.z-dig.com 2.6.32-504.el6.x86_64
172.16.1.110
[root@db-server ~]#

  二、为批量分发服务器安装 expect

[root@nfs-server ~]# yum -y install expect
...
Installed:
  expect.x86_64 0:5.44.1.15-5.el6_4                           

Complete!
[root@nfs-server ~]# which expect
/usr/bin/expect
[root@nfs-server ~]#

  三、脚本

  distribute.sh

[root@nfs-server ~]# cat /server/scripts/distribute/distribute.sh 
#!/bin/bash
#
# All of the machine shoud have the same root password,if it is not,you should change the scripts ,create a ip:root password file,use awk to get each useful var. by mr.zhou www.z-dig.com
#
. /etc/init.d/functions
# Define clientip "distributed client ip address,like:ip,ip,ip"

clientip=172.16.1.101,172.16.1.10,172.16.1.20,172.16.1.110,172.16.1.200

# Define username "distribute user (a normal user)"

username=distribute

# Define userpassword "distribute user's password"

userpassword=123456

# Define all machine 's root password (all root should have the same password)

rootpassword=localroot

# Define sshd port

sshdport=22

# Define expect timeout 

timeout=1

# Define distribute_sskeygen.exp and distribute_client.exp file path
sshkeygen_file=/server/scripts/distribute/distribute_sshkeygen.exp
client_file=/server/scripts/distribute/distribute_client.exp

# Create sudo script for distribute client
/bin/echo -e "#!/bin/bash\n/bin/echo \"$username ALL=(ALL) NOPASSWD:/bin/cp\">>/etc/sudoers" >/tmp/sudo.sh&&\

# Add local user
/usr/bin/id $username &>/dev/null
if [[ "$?" == "0" ]]
 then
  echo "local user $username already exists!"
  exit 1
fi
/usr/bin/which expect &>/dev/null
if [[ "$?" != "0" ]]
 then
  echo 'expect not installed ! you can use "yum -y install expect" to install expect.'
  exit 1
fi
/usr/sbin/useradd $username&&\
/bin/echo $userpassword|/usr/bin/passwd --stdin $username &>/dev/null &&\
/usr/bin/expect $sshkeygen_file $username $timeout &>/dev/null
for ip in `echo $clientip|tr "," "\n"`
 do
  /usr/bin/expect $client_file $ip $rootpassword $username $userpassword $timeout $sshdport &>/dev/null

/bin/ls -1v /tmp|/bin/grep distribute_check|/bin/awk -F "_" '{print $NF}'>/tmp/successip.txt&&\
/bin/grep -e "\b$ip\b" /tmp/successip.txt&>/dev/null
 if [[ "$?" == "0" ]]
   then
    action "$ip  initialization succeed !" /bin/true
   else
    action "$ip  initialization failed ! " /bin/false
 fi
done
rm -f /tmp/distribute_check*
rm -f /tmp/sudo.sh
rm -f /tmp/successip.txt
echo "Dig All Possible www.z-dig.com by mr.zhou"
[root@nfs-server ~]# 

  distribute_sshkeygen.exp

[root@nfs-server ~]# cat /server/scripts/distribute/distribute_sshkeygen.exp 
#!/usr/bin/expect
#Generate ssh pair key by mr.zhou
if { $argc != 2 } {
 send_user "Usage: username timeout\n"
 exit 1
}

set username [lindex $argv 0]
set timeout [lindex $argv 1]

spawn /bin/su - $username
expect {
       "$" {send "/usr/bin/ssh-keygen -t dsa\r"}
}
expect {
       "Enter file in which to save the key" {send "\r";exp_continue}
       "Enter passphrase" {send "\r";exp_continue}
       "Enter same passphrase again:" {send "\r";exp_continue}
}
expect eof
exit 
[root@nfs-server ~]# 

  distribute_client.exp

[root@nfs-server ~]# cat /server/scripts/distribute/distribute_client.exp    
#!/usr/bin/expect
#Crate nomoral user,sudo cp,check success,by mr.zhou
if { $argc != 6 } {
 send_user "Usage: expect iplist rootpasswd newusername userpasswd timeout sshdport\n"
 exit 1
}

set ip [lindex $argv 0]
set rootpasswd [lindex $argv 1]
set username [lindex $argv 2]
set userpasswd [lindex $argv 3]
set timeout [lindex $argv 4]
set sshdport [lindex $argv 5]

spawn /usr/bin/ssh -t -p $sshdport root@$ip "/usr/sbin/useradd $username&&/bin/echo $userpasswd|/usr/bin/passwd --stdin $username &>/dev/null"
expect {
       "yes/no" {send "yes\r";exp_continue}
       "password:" {send "$rootpasswd\r"}
}
expect eof

spawn /usr/bin/ssh-copy-id -i /home/$username/.ssh/id_dsa.pub "-p $sshdport $username@$ip"
expect {
       "yes/no" {send "yes\r";exp_continue}
       "password:" {send "$userpasswd\r"}
}
expect eof

spawn /bin/su - $username
expect {
       "$" {send "/usr/bin/scp -P$sshdport /tmp/sudo.sh $username@$ip:~ &>/dev/null\r"}
}
expect {
       "yes/no" {send "yes\r"}
}
expect eof

spawn /usr/bin/ssh -t -p $sshdport root@$ip "/bin/bash /home/$username/sudo.sh&&/bin/rm -f /home/$username/sudo.sh &>/dev/null"
expect {
       "yes/no" {send "yes\r";exp_continue}
       "password:" {send "$rootpasswd\r"}
}
expect eof
spawn /bin/su - $username
expect {
       "$" {send "/usr/bin/ssh -t -p $sshdport $username@$ip \"/bin/echo sucess>~/distribute.txt&&sudo cp ~/distribute.txt /root&&rm -f ~/distribute.txt\"\r"}
}
expect eof

spawn /usr/bin/scp -P $sshdport root@$ip:~/distribute.txt /tmp/distribute_check_$ip
expect {
       "yes/no" {send "yes\r";exp_continue}
       "password:" {send "$rootpasswd\r"}
}
expect eof
spawn /usr/bin/ssh -t -p $sshdport root@$ip "/bin/rm -f ~/distribute.txt &>/dev/null"
expect {
       "yes/no" {send "yes\r";exp_continue}
       "password:" {send "$rootpasswd\r"}
}
expect eof

exit
[root@nfs-server ~]# 

  distribute_sshkeygen.exp 作用是在分发服务器创建分发使用的普通账户。distribute_client.exp 作用是为分发客户端创建分发用的普通账户,并进行 sudo cp 的授权,对脚本初始化的结果进行检验等。可以在 distribute.sh 脚本中,定义一系列的参数,包括 ip , root 密码 ,指定分发账户,分发账户密码,等。可以根据实际情况对该脚本进行更改以适应不同的环境。为了达到测试的目的,在 ip 中增加了一个不存在的服务器 ip : 172.16.1.200

  四、执行 distribute.sh 脚本:

[root@nfs-server ~]# sh /server/scripts/distribute/distribute.sh 
172.16.1.101  initialization succeed !                     [  OK  ]
172.16.1.10  initialization succeed !                      [  OK  ]
172.16.1.20  initialization succeed !                      [  OK  ]
172.16.1.110  initialization succeed !                     [  OK  ]
172.16.1.200  initialization failed !                      [FAILED]
Dig All Possible www.z-dig.com by mr.zhou
[root@nfs-server ~]# 

  脚本执行成功,因为 172.16.1.200 未开机,所以提示初始化失败。

  五、终极测试,对之前的批量分发脚本做适当的修改,已完成批量分发 hosts 文件:

执行批量分发 hosts 脚本前,各客户端的 hosts 文件。使用分发服务器远程查看。

[root@nfs-server ~]# uname -n
nfs-server.z-dig.com
[root@nfs-server ~]# su - distribute
[distribute@nfs-server ~]$ ssh distribute@172.16.1.101 "uname -n&&cat /etc/hosts"
backup-server.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.101 backup-server.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.10 "uname -n&&cat /etc/hosts" 
lnmp-1.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.10 lnmp-1.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.20 "uname -n&&cat /etc/hosts" 
lamp-1.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.20 lamp-1.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.110 "uname -n&&cat /etc/hosts" 
db-server.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.110 db-server.z-dig.com
[distribute@nfs-server ~]$

  批量分发 hosts 脚本:

[distribute@nfs-server ~]$ cat /server/scripts/hosts-distribute.sh 
#!/bin/bash
# 
. /etc/init.d/functions
user=distribute
localfile=/home/distribute/hosts
port=22
remotepath=/etc/
for ip in {172.16.1.101,172.16.1.10,172.16.1.20,172.16.1.110,172.16.1.200}
 do
  scp -P $port $localfile $user@$ip:~ &>/dev/null &&\
  ssh -t $user@$ip sudo /bin/cp $localfile $remotepath &>/dev/null
if [[ "$?" == "0" ]]
 then
  action "$ip Distributed success!" /bin/true ;
 else
  action "$ip Distributed false!!!" /bin/false;
fi
done
[distribute@nfs-server ~]$ 

  执行脚本:

[distribute@nfs-server ~]$ sh /server/scripts/hosts-distribute.sh 
172.16.1.101 Distributed success!                          [  OK  ]
172.16.1.10 Distributed success!                           [  OK  ]
172.16.1.20 Distributed success!                           [  OK  ]
172.16.1.110 Distributed success!                          [  OK  ]
172.16.1.200 Distributed false!!!                          [FAILED]
[distribute@nfs-server ~]$ 

  在分发服务器端进行远程验证 hosts 文件:

[distribute@nfs-server ~]$ ssh distribute@172.16.1.101 "uname -n&&cat /etc/hosts"
backup-server.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.100 nfs-server.z-dig.com
172.16.1.101 backup-server.z-dig.com
172.16.1.10  lnmp-1.z-dig.com
172.16.1.20  lamp-1.z-dig.com
172.16.1.110 db-server.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.10 "uname -n&&cat /etc/hosts" 
lnmp-1.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.100 nfs-server.z-dig.com
172.16.1.101 backup-server.z-dig.com
172.16.1.10  lnmp-1.z-dig.com
172.16.1.20  lamp-1.z-dig.com
172.16.1.110 db-server.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.20 "uname -n&&cat /etc/hosts" 
lamp-1.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.100 nfs-server.z-dig.com
172.16.1.101 backup-server.z-dig.com
172.16.1.10  lnmp-1.z-dig.com
172.16.1.20  lamp-1.z-dig.com
172.16.1.110 db-server.z-dig.com
[distribute@nfs-server ~]$ ssh distribute@172.16.1.110 "uname -n&&cat /etc/hosts"  
db-server.z-dig.com
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
172.16.1.100 nfs-server.z-dig.com
172.16.1.101 backup-server.z-dig.com
172.16.1.10  lnmp-1.z-dig.com
172.16.1.20  lamp-1.z-dig.com
172.16.1.110 db-server.z-dig.com
[distribute@nfs-server ~]$ 

  测试成功。

  一键初始化部署批量分发环境脚本 下载。请根据具体的环境修改 distribute.sh 中定义的变量。


转载请注明原文链接:http://www.z-dig.com/deploying-a-bulk-distribution-to-expect-an-initial-key-server-and-client.html



正文部分到此结束