shell项目-分发系统-expect讲解


20.27 分发系统介绍


使用场景:

假如公司的业务做得越来越大,APP后端服务端所使用的编程语言是php,要想运行这个环境运行php代码,需要搭建lamp,lnmp的环境,最后还需要把代码上传到服务器上面。

在平时工作中,业务不断的迭代,有新的功能出现,这时候就需要更改代码,一台机器还好,甚至还可以在服务器上面更改,但是这样不规范,若干台,两三台的量还可以接受,如果机器特别多,甚至上百台的时候,这上百台机器存储的都是公司的站点。比如一个接口,APP访问量很大,APP需要调用服务端的接口,假如这个接口需要五十台机器去承载,那这时候就需要去搞一个分发系统了,能够让每天,每段时间更新的代码,分别的分布到这五十台机器上面去。


expect介绍

  • 可以说是一种脚本语言,它和shell比较相似,它可以实现传输文件,远程执行命令(不需要输入密码)

  • 它其实是一种上线代码的工具。

  • 上线:开发的代码,发布到线上环境。


准备工作以及过程:

  • 准备一台模板机器,这台机器上面的代码是最新的,准备要上线的代码。

  • 比如准备给50台机器上线,这50台机器的ip地址,用户和密码都需要知道

  • 使用expect脚本,借助于rsync把这些代码给推送到这50台机器上面去。假如需要在某机器上面执行命令,还可以远程执行这些命令。

  • 就是这样的一个过程。


20.28 expect脚本远程登录


1 安装expect

[root@centos7-01 ~]# yum install -y expect

2 编写expect脚本

目的:自动远程登录,并执行命令

[root@centos7-01 ~]# cd /usr/local/sbin/
 #! /usr/bin/expect
set host "192.168.189.129"
set passwd "?????"
#此处输入你的登录密码.
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
interact


脚本解释:

set host "192.168.189.129"
set passwd "?????"
spawn ssh root@$host
#远程登录的主机,以及密码,set host=$host,在except里,set设定变量
#spwan后接的是系统的shell命令,ssh远程登录,root@$host利用root登录进去
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
interact
#这是核心执行语句
"yes/no"表示第一次远程登录192.168.189.129,会提示"yes/no"。因为第一次登录,本机的/root/.ssh/know_hosts文件会误认为这是一台陌生的机器,严格上可能是不安全,所以会提示。
"yes/no" { send "yes\r"; exp_continue} 
#expect截取系统的提示,当遇到提示"yes/no"的时候,发送yes(yes\r,\表示回车键), exp_continue表示继续
"password:" { send "$passwd\r" }
#expect截取系统的提示,当遇到提示"password:"的时候,把密码(set passwd的变量)发送过去,
#expect支持用户交互
#interact结束

3 添加执行权限

[root@centos7-01 sbin]# chmod a+x 1.expect

4 执行脚本

[root@centos7-01 sbin]# ./1.expect 
spawn ssh root@192.168.189.129
root@192.168.189.129's password: 
Last login: Wed Jun  6 15:27:39 2018 from 192.168.189.1
[root@centos7-02 ~]#

5 查看ip地址

[root@centos7-02 ~]# ifconfig 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.189.129  netmask 255.255.255.0  broadcast 192.168.189.255
        inet6 fe80::b485:96d0:c537:251e  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:73:7c:4c  txqueuelen 1000  (Ethernet)
        RX packets 266  bytes 27149 (26.5 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 257  bytes 25678 (25.0 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

成功登录192.168.189.129,主机名也变了


20.29 expect脚本远程执行命令


1 必须在本机编写脚本,所以必须退出当前远程连接

[root@centos7-02 ~]# 登出
Connection to 192.168.189.129 closed.


2 改写脚本2.expect

目的:自动远程登录后,执行命令并退出

#!/usr/bin/expect
set user "root"
set passwd "远程登录的密码"
spawn ssh $user@192.168.133.132
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"


脚本解释:

#脚本分为2段,第一段是作为远程连接,第二段是远程登录后的操作。

expect "]*"

#expect "]*"这里的*表示用户的标识,#表示root用户,$表示普通用户

send "touch /tmp/12.txt\r"

#执行touch /tmp/12.txt\r命令,\r表示回车,这里算是确认执行的意思

expect "]*"
send "echo 1212 > /tmp/12.txt\r"

#执行echo 1212 > /tmp/12.txt\r,\r表示回车,

expect "]*"
send "exit\r"

#exit表示退出,登出

#interact与exit的区别:

  • interact 结束except脚本,但是它还停留在远程登录的机器上

  • exit 执行脚本结束,并退出当前登录状态

  • 如果2个参数都不加,远程登录后会马上退出登录状态


3 给予脚本执行权限


[root@centos7-01 sbin]# chmod a+x 2.expect

4 执行脚本

[root@centos7-01 sbin]# ./2.expect 
spawn ssh root@192.168.189.129
root@192.168.189.129's password: 
Last login: Wed Jun  6 15:51:19 2018 from 192.168.189.128
[root@centos7-02 ~]# touch /tmp/12.txt
[root@centos7-02 ~]# echo 1212 > /tmp/12.txt
[root@centos7-02 ~]# [root@centos7-01 sbin]#

5 检查当前所登录的机器

[root@centos7-01 sbin]# ifconfig 
ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.189.128  netmask 255.255.255.0  broadcast 192.168.189.255
        inet6 fe80::20c:29ff:fe15:5353  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:15:53:53  txqueuelen 1000  (Ethernet)
        RX packets 6552  bytes 6160724 (5.8 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 5049  bytes 447825 (437.3 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

进入到128,已退出129

6 进入129查看刚刚执行的命令

执行刚刚建立的远程登录脚本

[root@centos7-01 sbin]# ./1.expect 
spawn ssh root@192.168.189.129
root@192.168.189.129's password: 
Last login: Wed Jun  6 16:18:03 2018 from 192.168.189.128

查看远程登录后的执行结果

[root@centos7-02 ~]# ls -l /tmp/12.txt 
-rw-r--r-- 1 root root 5 6月   6 16:18 /tmp/12.txt
[root@centos7-02 ~]# cat !$
cat /tmp/12.txt
1212




20.30 expect脚本传递参数


1 编写脚本3.expect

[root@centos7-01 sbin]# vim 3.expect
#!/usr/bin/expect
set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "input your password...."
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] 把第一个参数设为user

set host [lindex $argv 1] 把第二个参数设为host

set cm [lindex $argv 2]   把第三个参数设为cm(执行的命令)


2 给予3.expect执行权限

[root@centos7-01 sbin]# chmod a+x 3.expect

3 执行脚本

[root@centos7-01 sbin]# ./3.expect root 192.168.189.129 ls
spawn ssh root@192.168.189.129
root@192.168.189.129's password: 
Last login: Wed Jun  6 16:19:53 2018 from 192.168.189.128
[root@centos7-02 ~]# ls
1.txt   2a.txt  3.txt   aa.txt           a.txt  network-test
22.txt  2.txt   a2.txt  anaconda-ks.cfg  A.txt

解释说明:

# ./3.expect root 192.168.189.129 ls 

刚刚脚本定义了配置参数,执行脚本后的第一个参数是user 第二个是host主机,第三个参数是命令,那么对应起来就是一目了然了。

3.1 传递执行多条命令

多个传递命令用""标起,

传递命令分别是:ls;w;cd /tmp/;pwd

./3.expect root 192.168.189.129 "ls;w;cd /tmp/;pwd"
spawn ssh root@192.168.189.129
root@192.168.189.129's password: 
Last login: Wed Jun  6 16:53:24 2018 from 192.168.189.128
[root@centos7-02 ~]# ls;w;cd /tmp/;pwd
1.txt   2a.txt  3.txt   aa.txt           a.txt  network-test
22.txt  2.txt   a2.txt  anaconda-ks.cfg  A.txt
 16:54:40 up  1:28,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.189.1    15:27    1:27m  0.01s  0.01s -bash
root     pts/1    192.168.189.128  16:54    0.00s  0.01s  0.00s w
/tmp

3.2 输出正常.done.