三十三次课

分发系统介绍

expect 是一个用来实现自动交互功能的软件,是基于tool command Language脚本语言的编程工具。

在现今的企业运维中, 自动化运维已经成为运维的主流趋势,
但是在很多情况下,执行系统命令或程序时,系统会以交互式的形式要求运维人员输入指定的字符串,之后才能继续执行命令。
例如为用户设置密码时,一般情况下就需要手工输入2次密码。

expect可以让我们实现自动登录远程机器,并且可以实现自动远程执行命令。当然若是使用不带密码的密钥验证同样可以实现自动登录和自动远程执行命令。但当不能使用密钥验证的时候,我们就没有办法了。所以,这时候只要知道对方机器的账号和密码就可以通过expect脚本实现登录和远程命令。

expect脚本远程登录

安装expect

# yum install -y expect

自动远程登录脚本

实验需要两台主机
主机1:10.1.1.32
主机2:10.1.1.30

# vi 1.expect

#!/usr/bin/expect
set host "10.1.1.30"     # 设置变量,目标主机的ip
set passwd "123456"      # 设置变量,目标主机的密码
spawn ssh root@$host     # 自动交互开始,在Expect自动交互程序执行的过程中,spawn命令是一开始就需要使用的命令
expect {                 # expect命令用于匹配交互信息,输入争正确的交互内容。
"yes/no" { send "yes\n";exp_cuntinue }  #匹配出现 "yes/no" 的行,{输入yes\n,\n就是换行符,} #exp_countinue  表示继续匹配,只要不是交互过程的最后一行都要在后后面加上这个命令
"assword:" { send "$passwd\n" }  #输入密码 $passwd\n 。匹配的字符串不加p是因为不清楚是大写还是小写
}
interact   #interact表示expect脚本结束了

# 注: 大括号的两边都需要有空格

测试是否可用

// 先给脚本加上执行权限
# chmod 755 1.expect

// 执行脚本
#  ./1.expect 
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Tue Jul 26 23:40:29 2018 from 10.1.1.170
[root@zabbix-server ~]# 
// 可以正常登陆到目标主机就算成功了

expect脚本远程执行命令

自动登陆后,执行命令后退出

// 2.expect  脚本文件的内容如下
# vi 2.expect

#!/usr/bin/expect
set host "10.1.1.30"
set passwd "123456"
spawn ssh root@$host
expect {
"yes/no" { send "yes\n"; exp_continue}
"assword:" { send "$passwd\n"}
}
expect "]*"                     # 匹配字符串 ]*   *号代表通配任意字符
send "touch /tmp/ecpect.txt\r"  # 输入命令 touch /tmp/ecpect.txt 这里命令结尾的\r 与前面的\n效果类似
expect "]*"
send "echo "expect test"  > /tmp/ecpect.txt\r" # 输入命令 echo "expect test" >/tmp/ecpect.txt
expect "]*"
send "exit\r"                    # 输入命令 exit   退出目标主机

测试脚本效果

// 加执行权限
[root@shell ~]> chmod 755 2.expect

// 执行脚本 后边的全是自动输入的
[root@shell ~]> ./2.expect 
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 00:54:02 2018 from 10.1.1.32
[root@zabbix-server ~]# touch /tmp/expect.txt
[root@zabbix-server ~]# echo 'expect test' > /tmp/expect.txt
[root@zabbix-server ~]# [root@shell ~]> 最后退出了10.1.1.30 回到到了当前的主机 

// 再次登录10.1.1.30 查看文件是否创建OK
[root@shell ~]> ./1.expect 
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 01:10:51 2018 from 10.1.1.32
[root@zabbix-server ~]# cat /tmp/expect.txt 
expect test
// 文件内容没问题。

expect脚本传递参数

// 3.expect 脚本文件内容如下
# vi 3.expect

#!/usr/bin/expect
set user [lindex $argv 0]  #  调用第一个参数  给变量user   用户名
set host [lindex $argv 1]  # 调用第二个参数 给变量host     ip
set passwd "123456"
set cm [lindex $argv 2]    #调用第三个参数 给变量cm       需要执行的命令
spawn ssh $user@$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
set timeout -1  # -1表示永远不超时,1表示1秒,2表示2秒....,表示执行命令几秒后停止
expect "]*"
send "exit\r"

测试脚本效果

// 加执行权限
[root@shell ~]> chmod 755 3.expect 

// 执行脚本,带上参数,第一个参数是登录目标主机的用户, 第二个参数是目标主机的ip 第三个参数是需要执行的命令
[root@shell ~]> ./3.expect root 10.1.1.30 "echo 'parameter test' >> /tmp/expect.txt"
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 01:13:59 2018 from 10.1.1.32
[root@zabbix-server ~]# echo 'parameter test' >> /tmp/expect.txt
[root@zabbix-server ~]# [root@shell ~]> 

//再次执行脚本  执行的命令是查看目标主机下 /tmp/expect.txt 的文件内容
[root@zabbix-server ~]# [root@shell ~]> ./3.expect root 10.1.1.30 "cat /tmp/expect.txt"
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 01:27:07 2018 from 10.1.1.32
[root@zabbix-server ~]# cat /tmp/expect.txt
expect test
parameter test

expect脚本同步文件

// 4.expect 脚本文件内容
# vi 4.expect

#!/usr/bin/expect
set passwd "123456"
spawn rsync -av root@10.1.1.30:/tmp/expect.txt /tmp/  #核心命令
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof    
// 当一个命令需要一定时间才能执行完的情况下,脚本最后需要加expect eof命令, 可以等待命令执行完毕才会结束脚本
// 还有在send执行的shell命令的下一行添加一个超时时间  timeout , 
   例如: timeout 5 为5秒超时。 -1为永不超时

测试脚本效果

[root@shell ~]> chmod 755 4.expect
[root@shell ~]> ./4.expect 
spawn rsync -av root@10.1.1.30:/tmp/expect.txt /tmp/
root@10.1.1.30's password: 
receiving incremental file list
expect.txt

sent 43 bytes  received 123 bytes  110.67 bytes/sec
total size is 27  speedup is 0.16

// 查单本地的/tmp目录下是否有expect.txt文件
[root@shell ~]> cat /tmp/expect.txt 
expect test
parameter test
// 同步成功

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

指定目标主机和需要同步的文件, 将文件同步到目标主机上,此方式只能同步一个文件或者目录

指定host和要同步的文件

# vi 5.expect
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]   #第一个参数指定目标主机的ip
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@shell ~]> mkdir testdir
[root@shell ~]> touch testdir/testfile.txt

// 执行脚本
[root@shell ~]> chmod 755 5.expect
[root@shell ~]> ./5.expect 10.1.1.30 /root/testdir/   //参数使用刚才创建目录的绝对路径 
spawn rsync -av /root/testdir/ root@10.1.1.30:/root/testdir/
root@10.1.1.30's password: 
sending incremental file list
created directory /root/testdir
./
testfile.txt

sent 113 bytes  received 74 bytes  374.00 bytes/sec
total size is 0  speedup is 0.00

// 检查10.1.1.30 的/root 目录下是否有同步过去的文件
[root@zabbix-server ~]> tree /root/
/root/
├── anaconda-ks.cfg
└── testdir
    └── testfile.txt

1 directory, 2 files
// 同步成功

构建文件分发系统

需求背景

对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。

实现思路

首先要有一台模板机器,把要分发的文件准备好,

然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。

核心命令

rsync -av –files-from=list.txt / root@host:/

文件分发系统的实现

定义用于同步文件的expect脚本

// rsync.expect 脚本文件内容
# vi 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:/    # R选项可以在目标主机中不存在同步的目录时自动创建相关目录 
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

创建一个存放文件路径的列表文件
增加如下需要同步的文件路径

//file.list内容,为同步的文件路径列表
# vi /tmp/file.list

/root/111/111.txt
/data/wwwroot/222.txt
/tmp/2333.txt

创建列表文件中的相关文件,用于实验

[root@shell ~]> mkdir /root/111
[root@shell ~]> mkdir /data/wwwroot/ -p
[root@shell ~]> touch `cat files.list`

创建一个主机IP列表文件

# vi /tmp/ip.list

127.0.0.1
10.1.1.30

创建一个循环同步的shell脚本

# vi rsync.sh

#!/bin/bash
for ip in `cat ips.list`
do
    echo $ip
    ./rsync.expect $ip files.list
done

测试脚本效果

// 给脚本文件执行权限
[root@shell ~]> chmod 755 rsync.sh rsync.expect

// 执行脚本 rsync.sh
[root@shell ~]> ./rsync.sh 
10.1.1.30
spawn rsync -av --files-from=./files.list / root@10.1.1.30:/
root@10.1.1.30's password: 
building file list ... done
data/
data/wwwroot/
data/wwwroot/222.txt
root/
root/111/
root/111/111.txt
tmp/
tmp/2333.txt

sent 344 bytes  received 88 bytes  864.00 bytes/sec
total size is 0  speedup is 0.00

// 查看10.1.1.30主机上是否有刚才同步过去的文件
[root@zabbix-server ~]> ls -dl /data/wwwroot/222.txt /root/111/111.txt  /tmp/2333.txt 
-rw-r--r--. 1 root root 0 8月   3 11:47 /data/wwwroot/222.txt
-rw-r--r--. 1 root root 0 8月   3 11:47 /root/111/111.txt
-rw-r--r--. 1 root root 0 8月   3 11:47 /tmp/2333.txt
// 同步成功

注意:这个文件分发系统有一个弊端,所有同步的主机都需要使用相同的密码, 而且有泄露密码的风险。
但是也可以使用密钥认证登录的方式来解决这个问题。

批量远程执行命令

思路:创建一个执行指定命令的expect脚本, 然后使用一个shell脚本来循环执行这个expect脚本

创建 exe.expect 脚本文件,内容如下

# vim 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"

创建 exe.sh 脚本文件,内容如下, 这里又用到了之前的 ips.list 主机列表文件

# vim exe.sh

#!/bin/bash
for ip in `cat ip.list`  # 遍历主机IP列表
do
    echo $ip
    ./exe.expect $ip "w;free -m;df -h"  执行exe.expect脚本, 指定主机ip 和需要执行的命令 
done

测试脚本效果

[root@shell ~]> ./exe.sh 
10.1.1.30
spawn ssh root@10.1.1.30
root@10.1.1.30's password: 
Last login: Fri Aug  3 10:16:16 2018 from 10.1.1.128
[root@zabbix-server ~]# w;free -h;df -h
 12:27:53 up  2:36,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     tty1                      09:52    1:58m  0.05s  0.05s -bash
root     pts/0    10.1.1.1         10:03    2:33   0.05s  0.05s -bash
root     pts/1    10.1.1.128       12:27    0.00s  0.03s  0.02s w
              total        used        free      shared  buff/cache   available
Mem:           976M        138M        437M        6.8M        400M        646M
Swap:          2.0G          0B        2.0G
文件系统                 容量  已用  可用 已用% 挂载点
/dev/mapper/centos-root   27G  1.1G   26G    4% /
devtmpfs                 478M     0  478M    0% /dev
tmpfs                    489M     0  489M    0% /dev/shm
tmpfs                    489M  6.8M  482M    2% /run
tmpfs                    489M     0  489M    0% /sys/fs/cgroup
/dev/sda1               1014M  125M  890M   13% /boot
tmpfs                     98M     0   98M    0% /run/user/0


// 执行成功

扩展

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值