1.分发系统介绍
如今一些比较大的企业,大都使用了负载均衡,而有时因为一些程序要更改,或者有些bug要修改,快速更新代码等,如果仅是几台server的话,很简单,把已经改好的程序拷过去,或者rsync远程推送,再或者网上NFS共享一下就可以了;但如果有几十台几百台,那样的方法会太繁琐,此时就可以用expect来批量实现分发任务。
-
expect:一个实现自动交互功能的软件套件,基于Tcl的一种脚本语言,具有简单的语法;
-
功 能 :实现自动登录远程机器,并自动执行命令;和shell脚本结合,可以实现完全自动化;
-
注 意:若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令。但当不能使用密钥验证的时候,我们就没有办法了。所以,这时只知道对方机器的账号和密码可以通过expect脚本实现登录和远程命令。
2.expect脚本远程登录
expect 远程登录脚本:
#!/usr/bin/expect
set host "192.168.139.132"
set passwd "password"
spawn ssh root@$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"assword:" { send "$passwd\r" }
}
interact
测试脚本:
//执行脚本先是提示是否连接,然后提示输入密码就能成功连接了
[root@knightlai02 ~]# expect /root/shell/expect.sh
spawn ssh root@192.168.139.132
The authenticity of host '192.168.139.132 (192.168.139.132)' can't be established.
ECDSA key fingerprint is SHA256:JEmKUtRSqXMbbymFgNEWnDQEgCUTjzFYFays6NrK58c.
ECDSA key fingerprint is MD5:2c:c4:cf:bc:1a:b8:f5:e2:03:2c:22:c3:0f:53:5c:be.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.139.132' (ECDSA) to the list of known hosts.
root@192.168.139.132's password:
Last login: Mon Oct 22 02:45:44 2018 from knight-pc.airdream
[root@knightlai02 ~]# ls
! 1.txt 2.txt a anaconda-ks.cfg sx sysconfig test.txt
3.expect脚本远程执行命令
3.1 远程登录并执行命令脚本:
#!/usr/bin/expect
set user "root"
set passwd "password"
spawn ssh $user@192.168.139.132
expect {
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"
send "touch /root/20181026.txt\r"
expect "]*"
send "echo 1212 > /root/20181026.txt\r"
expect "]*"
send "exit\r"
3.2 测试脚本:
//执行远程登录并执行命令 创建一个文件并写入“1212”
[root@knightlai02 ~]# expect /root/shell/expect1.sh
spawn ssh root@192.168.139.132
root@192.168.139.132's password:
Last login: Mon Oct 22 02:58:02 2018 from 192.168.139.134
[root@knightlai02 ~]# touch /root/20181026.txt
[root@knightlai02 ~]# echo 1212 > /root/20181026.txt
//在132机器上查看运行结果,看到了一个我们在134机器上面创建的文件
[root@knightlai02 ~]# ls
! 1.txt 2.txt a anaconda-ks.cfg sx sysconfig test.txt
[root@knightlai02 ~]# ls
! 1.txt 20181026.txt 2.txt a anaconda-ks.cfg sx sysconfig test.txt
[root@knightlai02 ~]# cat 20181026.txt
1212
4.expect脚本传递参数
4.1 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"
4.2 测试脚本:
//这里传递3个参数,一个是用户名,一个是主机地址,一个是要执行的命令
[root@knightlai02 ~]# expect /root/shell/expect2.sh root 192.168.139.132 ""ls /root/20181026.txt""
spawn ssh root@192.168.139.132
root@192.168.139.132's password:
Last login: Mon Oct 22 03:15:55 2018 from 192.168.139.134
[root@knightlai02 ~]# ls
! 1.txt 20181026.txt 2.txt a anaconda-ks.cfg sx sysconfig test.txt
5.expect脚本同步文件
5.1 编写expect同步文件脚本
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av root@192.168.139.132:/root/20181026.txt /root/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
5.2 测试脚本
//没有同步之前/root/下面是没有这个文件的
[root@knightlai02 ~]# ls
! a anaconda-ks.cfg mon shell sx sysconfig test.txt
//执行这个脚本将132机器上面的文件/root/20181026.txt同步过来
[root@knightlai02 ~]# expect /root/shell/expect3.sh
spawn rsync -av root@192.168.139.132:/root/20181026.txt /root/
root@192.168.139.132's password:
receiving incremental file list
20181026.txt
sent 43 bytes received 102 bytes 290.00 bytes/sec
total size is 5 speedup is 0.03
[root@knightlai02 ~]# ls
! 20181026.txt a anaconda-ks.cfg mon shell sx sysconfig test.txt
6.expect脚本指定host和要同步的文件
6.1 编写指定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
6.2 测试脚本
//指定两个参数 要同步的主机和要同步的文件
[root@knightlai02 ~]# expect /root/shell/expect4.sh 192.168.139.132 /root/test.txt
spawn rsync -av /root/test.txt root@192.168.139.132:/root/test.txt
root@192.168.139.132's password:
sending incremental file list
sent 47 bytes received 12 bytes 118.00 bytes/sec
total size is 974 speedup is 16.51
7.构建文件分发系统
7.1 需求
需求背景对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
实现思路:
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
核心命令rsync -av --files-from=list.txt / root@host:/
7.2 主要脚本:
首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
rsync.expect 内容
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av --files-from=$file / root@$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof
ip.list内容
192.168.139.132
192.168.139.133
......
rsync.sh 内容
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./rsync.expect $ip list.txt
done
注:rsync.expect与rsync.sh必须在同一目录下
8.批量远程执行命令
现在能够批量同步文件了,但是还不行,因为我们配置文件更改完成之后,就需要启动服务,重启服务是需要登录远程机器上执行命令,所以执行命令还得需要去写一个执行命令的脚本。
8.1 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"
e8.2 exe.sh
#!/bin/bash
for ip in `cat ip.list`
do
echo $ip
./exe.expect $ip "w;free -m;ls /tmp"
done
注意: expect eof 会退出远程的机器, interact 不会退出那机器。
9. 扩展 expect 语法介绍
shell脚本需要交互的地方可以使用 Here 文档是实现,但是有些命令却需要用户手动去就交互如passwd、scp。对自动部署免去用户交互很痛苦,expect能很好的解决这类问题。
1. expect的核心是spawn expect send set
spawn:调用要执行的命令
expect:等待命令提示信息的出现,也就是捕捉用户输入的提示:
send:发送需要交互的值,替代了用户手动输入内容
set:设置变量值
interact:执行完成后保持交互状态,把控制权交给控制台,这个时候就可以手工操作了。如果没有这一句登录完成后会退出,而不是留在远程终端上。
expect eof:这个一定要加,与 spawn 对应表示捕获终端输出信息终止,类似于 if....endif
expect 脚本必须以 interact 或 expect eof 结束,执行自动化任务通常 expect eof 就够了。
2. 设置 timeout
设置 expect 永不超时
set timeout -1
设置 expect 300 秒超时,如果超过 300 没有 expect 内容出现,则推出
set timeout 300