2018-08-01(expect分发系统)

20.27 分发系统介绍

公司业务逐渐扩大时,假如使用的网站或者APP的后端服务器所使用的语言是PHP,如果要想运行PHP代码,需要配置一个lamp或lnmp的环境,最后还需要把代码上传到服务器上去,但是在平常工作中经常有一些新的业务改变,这个时候就需要去修改代码,如果服务器不多还可以快速的在服务器上修改,但是如果有50台或更多服务器,那么就不可能直接在服务器进行修改了,这个时候就可以使用到分发系统这样的上线工具进行上线,发布上线代码,所谓的分发系统也就是上线的shell脚本,最核心的东西就是expect,expect也可以说是一种脚本语言,和shell很像,可以用它去实现传输文件,还可以实现自动远程登录执行命令,不需要输入密码。

使用什么工具上线代码,所谓上线就是把开发人员写的代码发布到线上环境去。

分发系统如何实现发布上线代码,首先要准备一台模板的机器,这台机器上的代码是最新的代码,是需要准备上线的代码,另外要给这50台电脑上线代码,还需要知道50台电脑的IP和对应的用户密码,然后使用expect脚本借助于rsync把这些代码推送到50台机器上,假如说还需要执行一些命令,还可以使用expect远程登录后去执行命令,就是这样的一个过程实现新代码上线发布。

20.28 expect脚本远程登录

1、yum安装expect 软件包

[root@localhost ~]# yum install -y expect

2、编写expect脚本
示例1:通过expect脚本自动远程登录,并执行命令

[root@localhost ~]# cat ssh.expect 
#! /usr/bin/expect
#定义主机变量
set host "192.168.66.132" 
#定义密码变量
set passwd "*****55"   
#远程登陆机器的语句
spawn ssh root@$host  
#初次登陆会有yes和no的提示
expect {
"yes/no" { send "yes\r"; exp_continue}  
"password:" { send "$passwd\r" }
}
interact

•别忘记给脚本加上执行权限

[root@localhost ~]# chmod a+x ssh.expect

3、执行效果

[root@localhost ~]# ./ssh.expect 
spawn ssh [email protected]

Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.66.132' (ECDSA) to the list of known hosts.
[email protected]'s password: 
Last login: Fri Aug  3 15:30:28 2018 from 192.168.66.1
[root@lnmp-server ~]#    已经自动登录到192.168.66.132 这台机器

20.29 expect脚本远程执行命令

示例2:通过expect脚本自动远程登录,并执行命令最后退出。

[root@localhost sbin]# vi touch.expect

#!/usr/bin/expect
set user "root"
set passwd "*****55"
spawn ssh [email protected]

expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/test.txt\r"
expect "]*"
send "echo haha > /tmp/test.txt\r"
expect "]*"
send "exit\r"

•别忘记给脚本加上执行权限

[root@localhost sbin]# chmod a+x touch.expect

执行效果

[root@localhost sbin]# ./touch.expect       
spawn ssh [email protected]                #因为不是第一次登陆了,所以没有yes or no的提示
[email protected]'s password: 
Last login: Fri Aug  3 15:50:39 2018 from 192.168.66.131
[root@lnmp-server ~]# touch /tmp/test.txt
[root@lnmp-server ~]# echo haha > /tmp/test.txt
[root@lnmp-server ~]# [root@localhost sbin]#

查看192.168.66.132/tmp目录是否自动创建了test.txt

[root@lnmp-server ~]# ll /tmp/test.txt 
-rw-r--r-- 1 root root 5 8月   3 15:50 /tmp/test.txt
[root@lnmp-server ~]# cat /tmp/test.txt 
haha

•比较ssh.expect和touch.expect脚本的区别,ssh.expect脚本仅仅是登录进去,然后interact表示expect脚本结束了,但是会停留在机器上不会退出登录的机器,touch.expect脚本登录完之后,还需要执行几条命令,最后才是退出结束脚本

[root@localhost ~]# cat ssh.expect 
#! /usr/bin/expect
#定义主机变量
set host "192.168.66.132" 
#定义密码变量
set passwd "*****55"   
#远程登陆机器的语句
spawn ssh root@$host  
#初次登陆会有yes和no的提示
expect {
"yes/no" { send "yes\r"; exp_continue}  
"password:" { send "$passwd\r" }
}
interact

[root@localhost sbin]# cat touch.expect 
#!/usr/bin/expect
set user "root"
set passwd "*****55"
spawn ssh [email protected]
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /tmp/test.txt\r"
expect "]*"
send "echo haha > /tmp/test.txt\r"
expect "]*"
send "exit\r"

20.30 expect脚本传递参数

shell脚本可以传递参数,expect也是可以传递参数的,不同的是expect的参数是从0开始的
示例3:expect脚本传递参数

 [root@jimmylinux-001 sbin]# vi 3.expect 
 #!/usr/bin/expect
 set user [lindex $argv 0]
 set host [lindex $argv 1]
 set passwd "*****55"
 set cm [lindex $argv 2]
 spawn ssh $user@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

•别忘记给脚本加上执行权限

[root@localhost sbin]# chmod +x 3.expect

执行脚本测试

###传递多条命令,需要使用双引号引起来,中间用分号分隔。
[root@localhost sbin]# ./3.expect root 192.168.66.132 "ls;w;vmstat 1 3"
spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 15:51:37 2018 from 192.168.66.131
[root@lnmp-server ~]# ls;w;vmstat 1 3
1.txt  2.sh  3.sh  anaconda-ks.cfg
 16:05:41 up 38 min,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.66.1     15:30   14:37   0.00s  0.00s -bash
root     pts/1    192.168.66.131   16:05    0.00s  0.00s  0.00s w
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 2  0      0 272780   2076 155580    0    0    55     5   75   95  0  0 98  1  0
 0  0      0 272780   2076 155600    0    0     0     0   59   60  0  1 99  0  0
 0  0      0 272780   2076 155600    0    0     0     0   55   53  0  0 100  0  0

20.31 expect脚本同步文件

使用expect脚本实现在一台机器上把文件同步到另外一台机器上,这里需要用到核心命令rsync,如果是手动方式进行同步,那么还需要单独输入密码,所以没有脚本方式操作方便
•注意,因为用到了rsync命令,所以两边机器都要安装rsync

yum install -y rsync

示例4:自动同步文件

[root@localhost sbin]# vi 4.expect 
#!/usr/bin/expect
set passwd "*****55"
spawn rsync -av [email protected]:/tmp/test.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof  #如果不加这条语句,那么还没有开始执行数据传输,就马上结束了,甚至有可能还没有远程登录成功,就已经退出来了,所以脚本里面必须要加这条语句。

给脚本加执行权限,并执行脚本测试

[root@localhost sbin]# chmod +x 4.expect
[root@localhost sbin]# ./4.expect 
spawn rsync -av [email protected]:/tmp/test.txt /tmp/
[email protected]'s password: 
receiving incremental file list
test.txt
sent 43 bytes  received 98 bytes  282.00 bytes/sec
total size is 5  speedup is 0.04
[root@localhost sbin]# ll /tmp/test.txt 
-rw-r--r-- 1 root root 5 8月   3 15:51 /tmp/test.txt

20.32 expect脚本指定host和要同步的文件

之前的3.expect文件默认是10秒钟超时,当然也是可以增加超时时间甚至可以让永久不超时。
只需要在脚本文件中添加设置timeout的变量即可

set timeout 3  设置超时秒数,如果是-1表示永久不会超时

示例5:指定host和要同步的文件,这种方式只适合同步一个文件。

[root@localhost sbin]# vi 5.expect
 #!/usr/bin/expect
  set passwd "*****55"
  set host [lindex $argv 0]  
  set file [lindex $argv 1]  
  spawn rsync -av $file root@$host:$file  
  expect {
  "yes/no" { send "yes\r"}
 "password:" { send "$passwd\r" }
 }
expect eof

给脚本加执行权限,并执行脚本测试

[root@localhost sbin]# chmod +x 5.expect 
[root@localhost sbin]# ./5.expect 192.168.66.132 ./5.expect 
spawn rsync -av ./5.expect [email protected]:./5.expect
[email protected]'s password: 
sending incremental file list
5.expect
sent 310 bytes  received 35 bytes  690.00 bytes/sec
total size is 217  speedup is 0.63
切换到加外一台机查看
[root@lnmp-server ~]# ll
-rwxr-xr-x  1 root root   217 8月   3 16:27 5.expect

20.33 构建文件分发系统

需求背景:对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
实现思路:首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
•核心命令:rsync -av --files-from=list.txt / root@host:/
文件分发系统的实现
1、编写 rsync.expect

[root@localhost sbin]# vi rsync.expect
#!/usr/bin/expect
set passwd "*****55"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/  
##如果不确定对方机器有相同的路径,可以加-avR
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

•别忘记加上执行权限chmod +x rsync.expect

2、编写文件列表 file.list

[root@localhost sbin]# vi /tmp/file.list
/tmp/test1.txt 
/tmp/test2.txt 
/tmp/test3.txt

3、编写IP地址列表文件 ip.list

[root@localhost sbin]# vi /tmp/ip.list
192.168.66.129
192.168.66.132

4、创建 rsync.sh 循环调用rsync.expect去执行命令

[root@localhost sbin]# vi rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
./rsync.expect $ip /tmp/file.list
done

5、测试效果

[root@localhost sbin]# sh rsync.sh
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password: 
building file list ... done
tmp/
tmp/test1.txt
tmp/test2.txt
tmp/test3.txt
sent 168 bytes  received 56 bytes  89.60 bytes/sec
total size is 0  speedup is 0.00
spawn rsync -avR --files-from=/tmp/file.list / [email protected]:/
[email protected]'s password: 
building file list ... done
tmp/
tmp/test1.txt
tmp/test2.txt
tmp/test3.txt
sent 187 bytes  received 57 bytes  162.67 bytes/sec
total size is 0  speedup is 0.00
##切换到机器上查看
[root@lnmp-server ~]# ls /tmp/
test1.txt   test2.txt    test3.txt

20.34 批量远程执行命令

想批量远程执行命令,可以通过2个脚本来实现
1、创建 exe.expect 脚本

[root@localhost sbin]# vi exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "*****55"
set cm [lindex $argv 1]
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

2、添加执行权限

[root@localhost sbin]# chmod +x exe.expect

3、创建 exe.sh 脚本循环执行

[root@localhost sbin]# cat exe.sh 
#!/bin/bash
for ip in `cat /tmp/ip.list`
do 
./exe.expect $ip "hostname"
done

注意:/tmp/ip.list要自已创建
4、测试脚本

[root@lnmp-server ~]# [root@localhost sbin]# sh exe.sh 
spawn ssh [email protected]
[email protected]'s password: 
Last login: Wed Aug  1 20:16:03 2018 from 192.168.66.131
[root@localhost ~]# hostname
localhost.localdomain
[root@localhost ~]# spawn ssh [email protected]
[email protected]'s password: 
Last login: Fri Aug  3 16:57:29 2018 from 192.168.66.131
[root@lnmp-server ~]# hostname
lnmp-server

扩展:
shell多线程 http://blog.lishiming.net/?p=448
给你提供一本电子书 链接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b
shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll

猜你喜欢

转载自blog.51cto.com/13736286/2154183
今日推荐