一、分发系统介绍 场景:公司业务逐渐扩大,后端服务端使用的编程语言是PHP,要运行PHP的环境,需要配置LAMP或者LNMP环境,最后还需要把代码上传到服务器上去,但是业务在迭代,需要新增功能,一台机器还好,可以在机器上直接修改,但是这样做不规范,如果机器有几十台或者上百台机器都是这一个站点的,比如有一个接口,APP访问量很大,APP需要调用服务端的一个接口,假如这个接口有50台机器在承载,这时候,就需要做一个分发系统,能够把每天或者每一段时间更新的代码分别发发布到这50台机器上去,分发器其实就是上线的脚本,核心的东西叫做expect,expect也可以说是一种脚本语言,用它可以实现传输文件,还可以实现远程执行命令,不需要我们输入密码

具体实现如下: 准备一台模板的机器,这台机器上的代码是最新的代码(准备要上线的代码),给这50台机器上线,这50台机器的IP地址和对应账号的密码都要知道,使用expect脚本,借助于rsync把代码推送到50台机器上,加入需要执行一些命令,可以使用expect去登录执行一些命令,这样的一个过程。

二、expect脚本远程登录 [root@linux-01 sbin]# yum install -y expect //检查系统有没有安装expect 安装好之后就可以写expect脚本了 实例1: 自动远程登录,并执行命令 [root@linux-01 sbin]# vi 1.expect #! /usr/bin/expect set host "192.168.238.130" //远程连接130这台机器 set passwd "123456" spawn ssh root@$host expect { "yes/no" { send "yes\r"; exp_continue} //提示yes/no的时候说明/root/.ssh/known_hosts "password:" { send "$passwd\r" } } interact

//解释:"yes/no" { send "yes\r"; exp_continue} //提示yes/no的时候说明/root/.ssh/known_hosts文件里面没有连接这台机器的记录,是一台陌生的机器,会提示你是否继续连接,send "yes\r"初次登录给它发送yes,\r表示回车,exp_continue表示继续; interact表示继续停留在远程的机器上; interact这里也可以写 expect eof 表示登录到远程的机器上之后停留1-2秒退出远程机器

[root@linux-01 sbin]# chmod a+x 1.expect //给1.expect 执行权限 [root@linux-01 sbin]# ./1.expect //执行下脚本看是否可以连接到130这台机器上 spawn ssh root@192.168.238.130 The authenticity of host '192.168.238.130 (192.168.238.130)' can't be established. ECDSA key fingerprint is SHA256:XAsiANqeZBXKHHPOs2F7CVv4z0mcZ9i99JROujGXbl4. ECDSA key fingerprint is MD5:2f:28:55:22:14:2b:51:c3:8f:86:d1:e8:0f:cc:51:03. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.238.130' (ECDSA) to the list of known hosts. root@192.168.238.130's password: Last login: Wed Jul 11 21:21:01 2018 from 192.168.238.1 [root@linux-02 ~]# //证明是可以成功的登录到130机器上

三、expect脚本远程执行命令 实例2: 自动远程登录后,执行命令并退出 [root@linux-01 sbin]# vi 2.expect #!/usr/bin/expect set user "root" set passwd "123456" spawn ssh $user@192.168.238.130

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

//解释: expect "]" 当判断到是"]"时; send "touch /tmp/12.txt\r" 创建一个12.txt文件; expect "]" 接着运行命令; send "echo 1212 > /tmp/12.txt\r" 把1212输入到12.txt文件; expect "]" send "exit\r" 运行exit命令退出去 [root@linux-01 sbin]# chmod a+x 2.expect //给脚本执行权限 [root@linux-01 sbin]# ./2.expect spawn ssh root@192.168.238.130 root@192.168.238.130's password: Last login: Sun Jul 22 20:47:28 2018 from 192.168.238.128 [root@linux-02 ~]# touch /tmp/12.txt echo 1212 > /tmp/12.txt [root@linux-02 ~]# echo 1212 > /tmp/12.txt [root@linux-02 ~]# [root@linux-01 sbin]# [root@linux-01 sbin]#

我们可以到130机器上去验证下 [root@linux-01 sbin]# ./1.expect spawn ssh root@192.168.238.130 root@192.168.238.130's password: Last login: Sun Jul 22 22:07:41 2018 from 192.168.238.128 [root@linux-02 ~]# ls -l /tmp/12.txt -rw-r--r-- 1 root root 5 Jul 22 22:07 /tmp/12.txt

四、expect脚本传递参数 实例3: 传递参数 [root@linux-01 sbin]# vi 3.expect #!/usr/bin/expect

set user [lindex $argv 0] set host [lindex $argv 1] set passwd "123456" 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"

//解释: set user [lindex $argv 0]中$argv 0是第一个参数,把第一个参数的值赋给user,; set host [lindex $argv 1]中$argv 1是第二个参数; set cm [lindex $argv 2]中$argv 2是第三个参数

[root@linux-01 sbin]# chmod a+x 3.expect //给脚本执行权限 [root@linux-01 sbin]# ./3.expect root 192.168.238.130 ls //给脚本传递user host cm三个参数 spawn ssh root@192.168.238.130 root@192.168.238.130's password: Last login: Sun Jul 22 22:08:38 2018 from 192.168.238.128 [root@linux-02 ~]# ls 11.txt 123 2.txt anaconda-ks.cfg.1 zabbix-release-3.2-1.el7.noarch.rpm [root@linux-02 ~]# [root@linux-01 sbin]# [root@linux-01 sbin]# ./3.expect root 192.168.238.130 "ls;w;vmstat 1" //连续执行多个命令,expect一般默认远程登录时间是10秒钟就退出来了