20.27 分发系统介绍
20.28 expect脚本远程登录
#! /usr/bin/expect
set host "192.168.93.128"
set passwd "123456"
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"assword:" { send "$passwd\r" }
}
interact
set
定义变量spawn
执行命令expect
使用expect语句进行交互\r
表示回车exp_contunue
表示继续interact
表示继续交互expect eof
表示停留远程机器上一会儿再退出
20.29 expect脚本远程执行命令
#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh $user@192.168.93.128
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"
20.30 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"
[lindex $argv 0]表示要输入的第一个参数 如此类推
当要输入参数里面有多个命令是需要用""双引号括起来并使用;分号分开
可以在命令行的后面增加set timeout
来指定命令的超时时间 -1
为永远
20.31 expect脚本同步文件
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av root@192.168.93.128:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
20.32 expect脚本指定host和要同步的文件
#!/usr/bin/expect
set passwd "123456"
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
20.33 构建文件分发系统
[root@centos01 shell]# cat rsync.expect
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
[root@centos01 tmp]# cat ip.list
192.168.93.128
[root@centos01 tmp]# cat list.txt
/tmp/12.txt
/root/shell/qq.txt
20.34 批量远程执行命令
[root@centos01 tmp]# cat exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
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"
[root@centos01 tmp]# cat /tmp/ip.list
192.168.93.128
课堂串讲
20.27 分发系统介绍
20.28 expect脚本远程登录
20.29 expect脚本远程执行命令
20.30 expect脚本传递参数
20.27 分发系统介绍
公司的网站本来已经建好了,当公司的业务越来l越大时候就会需要实时更新代码,由于后端服务器有很多台来跑web服务。此时为了快速更新代码就可以使用分发系统。其中开源的上线代码的软件有很多,git等等。这里我们使用shell来编写一个分发系统来上线代码。核心使用expect脚本语言,它可以实现远程执行命令,远程传输数据等操作。
- 准备工作
1.准备1台模版机器,里面是包含有最新的代码
2.每台分发机器的IP地址和密码
3.分发系统脚本
由于分发系统的核心是使用expect,因此先实践几个例子来熟悉expect的语法命令
20.28 expect脚本远程登录
实例1.自动远程登录
expect脚本机器 kun05 192.168.80.104
被远程的机器 kun03 192.168.80.102
1.安装expect语言
1 | [root@kun05 ~]# yum install -y expect |
2.编辑脚本
1 2 | [root@kun05 ~]# cd /usr/local/sbin/ [root@kun05 sbin]# vim expect1.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 11 12 | #!/usr/bin/expect #定义变量 set host "192.168.80.102" set passwd "coco0769" #执行命令 spawn ssh root@$host #与远程机器交互 截取特定信息 发送变量 expect { "yes/no" { send "yes\r";exp_continue } "password:" { send "$passwd\r" } } interact |
set
定义变量spawn
执行命令expect
使用expect语句进行交互\r
表示回车exp_contunue
表示继续interact
表示继续交互expect eof
表示停留远程机器上一会儿再退出
为了让远程登录时候出现提示,可以清空/root/.ssh/known_hosts
目录
1 | [root@kun05 ~]# > /root/.ssh/known_hosts |
测试
1.添加执行权限
1 | [root@kun05 sbin]# chmod a+x expect1.exp |
2.执行脚本
1 2 3 4 5 6 7 8 9 10 | [root@kun05 sbin]# ./expect1.exp spawn ssh root@192.168.80.102 The authenticity of host '192.168.80.102 (192.168.80.102)' can't be established. ECDSA key fingerprint is SHA256:4QK/8Tn8lZAitB2+3wJMBuONgHExXkOAzZpYPndYoPQ. ECDSA key fingerprint is MD5:89:d5:7c:90:ff:d2:c6:1a:6e:f8:58:48:29:78:9a:f3. Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added '192.168.80.102' (ECDSA) to the list of known hosts. root@192.168.80.102's password: Last login: Thu Jul 19 21:52:22 2018 from 192.168.80.104 [root@kun03 ~]# |
已经成功登录kun03机器上
20.29 expect脚本远程执行命令
实例2.自动远程登录,并执行命令并退出
编辑脚本
1 | [root@kun05 sbin]# vim expect2.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/expect set user "root" set host "192.168.80.102" set passwd "coco0769" spawn ssh $user@$host expect { "yes/no" {send "yes\r";exp_continue} "password:" {send "$passwd\r"} } expect "]*" send "touch /tmp/test.aa\r" expect "]*" send "echo 111 >/tmp/test.aa\r" expect "]*" send "exit\r" |
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 | [root@kun05 sbin]# chmod a+x expect2.exp [root@kun05 sbin]# ./expect2.exp spawn ssh root@192.168.80.102 root@192.168.80.102's password: Last login: Thu Jul 19 22:48:29 2018 from 192.168.80.104 [root@kun03 ~]# touch /tmp/test.aa [root@kun03 ~]# echo 111 >/tmp/test.aa |
进入kun03机器看看
1 2 3 4 | [root@kun03 ~]# ll /tmp/test.aa -rw-r--r-- 1 root root 4 7月 19 22:50 /tmp/test.aa [root@kun03 ~]# cat /tmp/test.aa 111 |
20.28 expect脚本传递参数
实例3.远程传递参数
编辑脚本
1 | [root@kun05 sbin]# vim expect3.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | #!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd "coco0769" set cmd [lindex $argv 2] spawn ssh $user@$host expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect "]*" send "$cmd\r" expect "]*" send "exit\r" |
[lindex $argv 0]
表示要输入的第一个参数 如此类推
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 8 9 10 11 12 | [root@kun05 sbin]# chmod a+x expect3.exp [root@kun05 sbin]# ./expect3.exp root 192.168.80.102 "ls;w" spawn ssh root@192.168.80.102 root@192.168.80.102's password: Last login: Thu Jul 19 22:52:09 2018 from 192.168.80.1 [root@kun03 ~]# ls;w anaconda-ks.cfg ip_forwarx~ ip_forwarz~ logs temp ip_forward~ ip_forwary~ log sim.pid zabbix-release-3.4-2.el7.noarch.rpm 23:45:34 up 2:02, 2 users, load average: 0.01, 0.03, 0.05 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT root pts/0 192.168.80.1 22:52 7:58 0.01s 0.01s -bash root pts/1 192.168.80.104 23:45 0.00s 0.00s 0.00s w |
当要输入参数里面有多个命令是需要用""
双引号括起来并使用;
分号分开
可以在命令行的后面增加set timeout
来指定命令的超时时间 -1
为永远
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | #!/usr/bin/expect set user [lindex $argv 0] set host [lindex $argv 1] set passwd "coco0769" set cmd [lindex $argv 2] spawn ssh $user@$host expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect "]*" send "$cmd\r" set timeout -1 expect "]*" send "exit\r" |
测试
输入vmstat命令
1 2 3 4 5 6 7 8 9 10 11 12 | [root@kun03 ~]# [root@kun05 sbin]# ./expect3.exp "root" 192.168.80.102 "vmstat 1" spawn ssh root@192.168.80.102 root@192.168.80.102's password: Last login: Fri Jul 20 21:42:43 2018 from 192.168.80.104 [root@kun03 ~]# vmstat 1 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 167852 2108 168580 0 0 35 3 85 113 0 0 99 0 0 0 0 0 167480 2108 168592 0 0 0 0 91 113 0 1 99 0 0 0 0 0 167480 2108 168592 0 0 0 0 104 119 0 0 100 0 0 0 0 0 167480 2108 168592 0 0 0 0 79 96 0 1 99 0 0 0 0 0 167480 2108 168592 0 0 0 0 89 106 0 0 100 0 0 |
现在是不断地执行vmstat命令
20.31 expect脚本同步文件
20.32 expect脚本指定host和要同步的文件
20.33 构建文件分发系统
20.34 批量远程执行命令
20.31 expect脚本同步文件
实例4.自动同步文件
编辑脚本
1 | [root@kun05 sbin]# vim expect4.exp |
写入下面代码
1 2 3 4 5 6 7 8 | #!/usr/bin/expect set passwd "coco0769" spawn rsync -av root@192.168.80.102:/tmp/test.aa /tmp/ expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect eof |
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 8 9 10 11 12 | [root@kun05 sbin]# chmod a+x expect4.exp [root@kun05 sbin]# ./expect4.exp spawn rsync -av root@192.168.80.102:/tmp/test.aa /tmp/ root@192.168.80.102's password: receiving incremental file list test.aa sent 43 bytes received 97 bytes 280.00 bytes/sec total size is 4 speedup is 0.03 [root@kun05 sbin]# ll /tmp/test.aa -rw-r--r-- 1 root root 4 7月 19 22:50 /tmp/test.aa |
已经把192.168.80.102的test.aa文件自动同步过来本机了
20.32 expect脚本指定host和要同步的文件
实例5.指定host和同步单个文件
编辑脚本
1 | [root@kun05 sbin]# vim expect5.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 | #!/usr/bin/expect set passwd "coco0769" 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 |
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 8 9 | [root@kun05 sbin]# chmod a+x expect5.exp [root@kun05 sbin]# ./expect5.exp 192.168.80.102 /tmp/test spawn rsync -av /tmp/test root@192.168.80.102:/tmp/test root@192.168.80.102's password: sending incremental file list test sent 85 bytes received 35 bytes 240.00 bytes/sec total size is 0 speedup is 0.00 |
20.33 构建文件分发系统
分发系统中首先用expect编写远程同步脚本
并指定文件列表
和目标IP列表
然后使用shell脚本
调用expect来同步文件。
这里每台机器必须使用同样的密码才可以同步,也可以让机器之前使用密钥
登录。还有让每台机器都安装上rsync
其核心命令为rsync -av --files-from=list.txt / root@host:/
1.编辑expect脚本
1 | [root@kun05 sbin]# vim rsync.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 11 | #!/usr/bin/expect set passwd "coco0769" set host [lindex $argv 0] set file [lindex $argv 1] #--file-from指定文件列表路径 -R表示同步时目标会级联创建目录 spawn rsync -avR --files-from=$file / root@$host:/ expect { "yes/no" {send "yes\r"} "password:" {send $passwd\r} } expect eof |
2.创建ip.list 同步机器的IP列表
1 2 3 4 | [root@kun05 sbin]# vim /tmp/ip.list 192.168.80.102 192.168.80.103 |
3.创建file.list 需要同步文件的列表
1 2 3 4 | [root@kun05 sbin]# vim /tmp/file.list /tmp/test /tmp/test.aa |
4.创建 rsync.sh 脚本
1 | [root@kun05 sbin]# vim rsync.sh |
写入下面代码
1 2 3 4 5 | #!/bin/bash for i in `cat /tmp/ip.list` do ./rsync.exp $i /tmp/file.list done |
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | [root@kun05 sbin]# chmod a+x rsync.exp [root@kun05 sbin]# sh +x rsync.sh spawn rsync -avR --files-from=/tmp/file.list / root@192.168.80.102:/ root@192.168.80.102's password: building file list ... done tmp/ tmp/test tmp/test.aa sent 185 bytes received 57 bytes 161.33 bytes/sec total size is 11 speedup is 0.05 spawn rsync -avR --files-from=/tmp/file.list / root@192.168.80.103:/ root@192.168.80.103's password: building file list ... done tmp/ tmp/test tmp/test.aa sent 185 bytes received 57 bytes 484.00 bytes/sec total size is 11 speedup is 0.05 |
20.34 批量远程执行命令
当同步完代码后有可能需要批量地重启服务,因此还需要批量远程执行命令,类似于自动化。
这里是用expect编写执行命令的脚本并用shell脚本来批量调用它。
1.编辑expect脚本
1 | [root@kun05 sbin]# vim exe.exp |
写入下面代码
1 2 3 4 5 6 7 8 9 10 11 12 13 | #!/usr/bin/expect set passwd "coco0769" set host [lindex $argv 0] set cmd [lindex $argv 1] spawn ssh root@$host expect { "yes/no" {send "yes\r"} "password:" {send "$passwd\r"} } expect "]*" send "$cmd\r" expect "]*" send "exit\r" |
2.编写shell脚本
1 | [root@kun05 sbin]# vim exe.sh |
写入下面代码
1 2 3 4 5 6 | #!/bin/bash for i in `cat /tmp/ip.list` do echo $i ./exe.exp $i "service nginx restart" done |
测试
添加执行权限并执行脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | [root@kun05 sbin]# chmod a+x exe.exp [root@kun05 sbin]# sh exe.sh 192.168.80.102 spawn ssh root@192.168.80.102 root@192.168.80.102's password: Last login: Fri Jul 20 23:40:28 2018 from 192.168.80.104 [root@kun03 ~]# service nginx restart Restarting nginx (via systemctl): [ 确定 ] 192.168.80.103 spawn ssh root@192.168.80.103 root@192.168.80.103's password: Last login: Fri Jul 20 23:38:46 2018 from 192.168.80.104 [root@kun04 ~]# service nginx restart Restarting nginx (via systemctl): [ 确定 ] |
这里kun03和kun04机器都执行了service nginx restart
命令