分发系统——expect

分发系统-expect

1、分发系统介绍

现在一些比较大的企业,大都使用了负载均衡,而有时由于一些程序要更改,或者有些bug要修改,快速更新代码等,若是仅是几台server的话,很简单,把已经改好的程序拷过去,或者rsync远程推送,再或者网上NFS共享一下就能够了;但若是有几十台几百台,那样的方法会太繁琐,此时就能够用expect来批量实现分发任务。shell

  • expect:一个实现自动交互功能的软件套件,基于Tcl的一种脚本语言,具备简单的语法;vim

  • 功 能 :实现自动登陆远程机器,并自动执行命令;和shell脚本结合,能够实现彻底自动化;bash

  • 注 意:如果使用不带密码的密钥验证一样能够实现自动登陆和自动远程执行命令。但当不能使用密钥验证的时候,咱们就没有办法了。因此,这时只知道对方机器的帐号和密码能够经过expect脚本实现登陆和远程命令。服务器

2、expect脚本远程登陆

本机试验环境:负载均衡

  • 主机端 ying01 192.168.112.136
  • 远程端1:ying02 192.168.112.138
  • 远程端2:ying02 192.168.112.139

进入/usr/local/sbin/,建立一个expect脚本;ssh

[root@ying01 ~]# cd /usr/local/sbin/
[root@ying01 sbin]# vim 1.expect

#! /usr/bin/expect
set host "192.168.112.138"         //设置链接主机 
set passwd "ssss1234"              //设置密码
spawn ssh root@$host               //执行命令
expect {                                   
"yes/no" { send "yes\r"; exp_continue}   //假如第一次登录,须要yse,而后回车,继续执行
"password:" { send "$passwd\r" }        //输入密码
}
interact                                //结束执行

代码解释: #! /usr/bin/expect 这一行告诉操做系统脚本里的代码使用那一个shell来执行。测试

  • 在expect下 定义变量,用 set,好比 定义变量a为1 :set a 1
  • expect 使用expect语句进行交互
  • \r表示回车
  • exp_continue 表示继续 \r 表示换行 interact 继续停留在这台机器,不退出。
  • interact表示继续交互

先用ssh 192.168.112.138 直接链接 ying02网站

[root@ying01 sbin]# ssh 192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 08:28:02 2018 from 192.168.112.1
[root@ying02 ~]# 登出
Connection to 192.168.112.138 closed.

授予1.expect 可执行权限,就能够链接ying02机器ui

[root@ying01 sbin]# ./ 1.expect 
-bash: ./: 是一个目录
[root@ying01 sbin]# ./1.expect 
-bash: ./1.expect: 权限不够
[root@ying01 sbin]# chmod a+x 1.expect 
[root@ying01 sbin]# ./1.expect 
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 15:22:34 2018 from 192.168.112.136
[root@ying02 ~]#

为了让远程登陆时候出现提示,能够清空/root/.ssh/known_hosts目录;而后执行1.except,能够看到脚本,自动执行spa

[root@ying01 sbin]# ls /root/.ssh/known_hosts
/root/.ssh/known_hosts
[root@ying01 sbin]# cat /root/.ssh/known_hosts     //有秘钥
192.168.112.136 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGrGzkv3dZLgXZVbExoHibbrjgfJ77FM/+pkylJJiPjNsuSPYpoPd3xJ6q7Uh8rKezv/1dAOI8Fh/Dnii9+GSH0=
192.168.112.138 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGrGzkv3dZLgXZVbExoHibbrjgfJ77FM/+pkylJJiPjNsuSPYpoPd3xJ6q7Uh8rKezv/1dAOI8Fh/Dnii9+GSH0=
[root@ying01 sbin]# > /root/.ssh/known_hosts     //清空
[root@ying01 sbin]# cat /root/.ssh/known_hosts
[root@ying01 sbin]# ./1.expect                   //执行
spawn ssh root@192.168.112.138
The authenticity of host '192.168.112.138 (192.168.112.138)' can't be established.
ECDSA key fingerprint is SHA256:ZQlXi+kieRwi2t64Yc5vUhPPWkMub8f0CBjnYRlX2Iw.
ECDSA key fingerprint is MD5:ff:9f:37:87:81:89:fc:ed:af:c6:62:c6:32:53:7a:ad.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.112.138' (ECDSA) to the list of known hosts.
root@192.168.112.138's password: 
Last login: Thu Aug  2 16:06:27 2018 from 192.168.112.136
[root@ying02 ~]#

3、 expect脚本远程执行命令

在ying01(192.168.112.136)上执行2.expect

[root@ying01 sbin]# vim 2.expect

#!/usr/bin/expect
set user "root"                        //设置用户为 root
set passwd "88888888"                  //设置密码
spawn ssh $user@192.168.112.138        //链接远程机器ying02

expect {                               //expect脚本内容
"yes/no" { send "yes\r"; exp_continue}
"password:" { send "$passwd\r" }
}
expect "]*"                            //遇到右侧方括号执行下面命令
send "touch /tmp/12.txt\r"             //在/tmp下建立12.txt;回车
expect "]*"                            //上一语句执行完,遇到右侧方括号,执行下面
send "echo 1212 > /tmp/12.txt\r"       //把1212写入12.txt,回车
expect "]*"                            
send "exit\r"                          //输入exit,退出,回到ying01机器

如今在ying02机器(192.168.112.138)上

[root@ying02 ~]# ls /tmp/12.txt              //12.txt存在
/tmp/12.txt
[root@ying02 ~]# ls -l /tmp/12.txt           //查看日期,证实是ying01远程建立的
-rw-r--r-- 1 root root 5 8月   2 17:43 /tmp/12.txt
[root@ying02 ~]# cat /tmp/12.txt             //查看内容,只有1212,那么证实试验正确  
1212

4、expect脚本传递参数

expect脚本能够接受从bash传递过来的参数.可使用[lindex $argv n]得到,n从0开始,分别表示第一个,第二个,第三个….参数

[root@ying01 sbin]# vim 3.expect

#!/usr/bin/expect
set user [lindex $argv 0]   //第一个参数
set host [lindex $argv 1]   //第二个参数
set passwd "88888888"
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"

给予可执行权限,并定义参数后执行脚本;

[root@ying01 sbin]# chmod a+x 3.expect
[root@ying01 sbin]# ./3.expect root 192.168.112.138 "ls;pwd"    //带参数执行;cm为定义变量,能够是任何命令,两命令之间应分号隔开
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 21:35:55 2018 from 192.168.112.136
[root@ying02 ~]# ls;pwd          //一、打开目录  二、查看所在行 
123.txt  5555555.txt      NBA
520.txt  999.txt          zabbix-release-3.2-1.el7.noarch.rpm
555      anaconda-ks.cfg  [电影天堂-www.dy2018.net]深海之战.720p.BD中文字幕.rmvb
/root
[root@ying02 ~]# [root@ying01 sbin]#

参数中能够定义多个命令:如执行pwd、w、rm、ls -ld、vmstat 1等,命令之间用分号隔开

[root@ying01 sbin]# ./3.expect root 192.168.112.138 "pwd;w;rm -vf 2q.txt;ls -ld;vmstat 1"
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Thu Aug  2 22:08:16 2018 from 192.168.112.136
[root@ying02 ~]# pwd;w;rm -vf 2q.txt;ls -ld;vmstat 1
/root                                                                //执行pwd
 22:09:08 up 13:42,  2 users,  load average: 0.00, 0.01, 0.05        //执行w
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    08:28    2:12   0.04s  0.04s -bash
root     pts/1    192.168.112.136  22:09    0.00s  0.01s  0.00s w
已删除"2q.txt"                                                       //执行rm
dr-xr-x---. 5 root root 4096 8月   2 22:09 .                         //执行ls
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----   //执行vmstat 1
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 1594252   2076 160452    0    0     1     1   51   46  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0   93   93  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  101   92  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0   99   98  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  115  103  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  106  102  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  105   95  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0    51  138  126  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  107   94  0  0 100  0  0
 0  0      0 1594324   2076 160516    0    0     0     0  139  117  0  0 100  0  0

5、expect脚本同步文件

在一台机器上把文件同步到多台机器上;核心命令,就是用的rsync服务。

[root@ying01 sbin]# vim 4.expect

#!/usr/bin/expect
set passwd "88888888"
spawn rsync -av root@192.168.181.135:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send $passwd\r}
}
expect eof  //结束expect匹配。

expect eof 语句解释:

  • spawn执行的命令结果,会被expect捕捉到。由于spawn会启动一个进程,只有这个进程的相关信息才会被捕捉到,主要包括:标准输入的提示信息,eof和timeout。
  • 在这里eof是必须去匹配的,在spawn进程结束后会向expect发送eof,若是expect没有匹配,那么会当即退出远程登陆,即操做失败。

受权并测试

[root@ying01 sbin]# chmod a+x 4.expect
[root@ying01 sbin]# ./4.expect 
spawn rsync -av root@192.168.112.138:/tmp/12.txt /tmp/
root@192.168.112.138's password: 
receiving incremental file list
12.txt

sent 43 bytes  received 97 bytes  93.33 bytes/sec
total size is 5  speedup is 0.04

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

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

[root@ying01 sbin]# vim 5.expect

#!/usr/bin/expect
set passwd "88888888"
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

受权,测试;

[root@ying01 sbin]# chmod a+x 5.expect
[root@ying01 sbin]# ./5.expect 192.168.112.138 "/tmp/12.txt"
spawn rsync -av /tmp/12.txt root@192.168.112.138:/tmp/12.txt
root@192.168.112.138's password: 
sending incremental file list

sent 45 bytes  received 12 bytes  114.00 bytes/sec
total size is 5  speedup is 0.09

注意:

一、这里要同步的文件,必要要写绝对路径;

二、备份的时候,注意时间限制;能够设定 set timeout 定义超时时间(单位为 秒) -1 为永远不超时。

7、构建文件分发系统

  • 需求背景

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

  • 实现思路

    首先要有一台模板机器,把要分发的文件准备好,而后只要使用expect脚本批量把须要同步的文件分发到目标机器便可。

  • 核心命令

    rsync -av --files-from=list.txt / root@host:/ 注意:这里的都是根目录

    使用rsync 的 --files参数,能够实现调用文件里面的列表,进行多个文件远程传输,进而实现文件分发文件分发系统的实现。

编写rsync.expect 脚本

[root@ying01 sbin]# vim rsync.expect

#!/usr/bin/expect
set passwd "ssss1234"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / root@$host:/ 
# 上传文件的列表是$file,咱们须要在list当中去定义; --file-from指定文件列表路径 -R表示同步时目标会级联建立目录
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

由于实现分发系统,确定是由于须要分发的机器数量过大,因此,定义好了 文件 的 list 列表文件之后, 还须要配置 ip 的列表文件

[root@ying01 sbin]# vim /tmp/ip.list

192.168.112.138
192.168.112.139

建立file.list 须要同步文件的列表

[root@ying01 sbin]# vim /tmp/file.list

/tmp/12.txt
/root/NBA
/root/grep
/221.txt

建立一个rsync的shell脚本,脚本的目的:遍历全部的server和list中的文件能够同步到每台服务器。

[root@ying01 sbin]# vim rsync.sh

#!/bin/bash

for ip in `cat /tmp/ip.list`
do
    echo $ip
    ./rsync.expect $i /tmp/file.list
done

受权rsync.expect脚本,并测试;

[root@ying01 sbin]# chmod a+x rsync.expect
[root@ying01 sbin]# sh -x rsync.sh       //执行rsync.sh脚本
++ cat /tmp/ip.list
+ for i in '`cat /tmp/ip.list`'
+ ./rsync.expect 192.168.112.138 /tmp/file.list   
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.112.138:/
root@192.168.112.138's password: 
building file list ... done
root/
root/221.txt
root/NBA/
root/grep/

sent 6,860 bytes  received 44 bytes  13,808.00 bytes/sec
total size is 6,625  speedup is 0.96
+ for i in '`cat /tmp/ip.list`'
+ ./rsync.expect 192.168.112.139 /tmp/file.list
spawn rsync -avR --files-from=/tmp/file.list / root@192.168.112.139:/
root@192.168.112.139's password: 
building file list ... done
root/
root/221.txt
root/NBA/
root/grep/
tmp/

sent 6,863 bytes  received 47 bytes  13,820.00 bytes/sec
total size is 6,625  speedup is 0.96

此时查看ying02机器:192.168.112.138

[root@ying02 ~]# ls
123.txt  555          anaconda-ks.cfg  zabbix-release-3.2-1.el7.noarch.rpm
221.txt  5555555.txt  grep             [电影天堂-www.dy2018.net]深海之战.720p.BD中文字幕.rmvb
520.txt  999.txt      NBA

ying03机器:192.168.112.139

[root@ying03 ~]# ls
123.txt  221.txt  520.txt  555  5555555.txt  999.txt  anaconda-ks.cfg  grep  NBA

分发系统还有一个重要的关键是,确保同步的机器的密码一致,不然将不能实现同步;因此这就存在一个弊端,一旦脚本暴露,将会让别人知道如何登录你机器;固然也有对应的解决办法,那就是使用密钥认证。

8、批量远程执行命令

当同步完代码后有可能须要批量地重启服务,所以还须要批量远程执行命令,相似于自动化。 这里是用expect编写执行命令的脚本并用shell脚原本批量调用它。

[root@ying01 sbin]# vim exe.expect

#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "ssss1234"
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的shell脚本,用来调用exe.expect脚本

[root@ying01 sbin]# vim exe.sh

#!/bin/bash
for ip in `cat /tmp/ip.list`                    //循环执行ip.list,注意ip清单是上个试验的;
do
    echo $ip                       
    ./exe.expect $ip "w;free -m;ls /tmp"       //调用exe的expect脚本,并传递参数;
done

给exe.expect可执行权,并进行测试

[root@ying01 sbin]# chmod a+x exe.expect 

[root@ying01 sbin]# sh -x exe.sh 
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.112.138
192.168.112.138
+ ./exe.expect 192.168.112.138 'w;free -m;ls /tmp'
spawn ssh root@192.168.112.138
root@192.168.112.138's password: 
Last login: Fri Aug  3 01:05:47 2018 from 192.168.112.136
[root@ying02 ~]# w;free -m;ls /tmp                                        //ying02下
 01:09:25 up 16:42,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    四08   38:45   0.04s  0.04s -bash
root     pts/1    192.168.112.136  01:09    0.00s  0.00s  0.00s w
              total        used        free      shared  buff/cache   available
Mem:           1831         129        1542          16         159        1530
Swap:          3813           0        3813
12.txt
systemd-private-1516b7edb3f14f5e82677137397bcc40-chronyd.service-ozGmlD
systemd-private-1516b7edb3f14f5e82677137397bcc40-vgauthd.service-jhUiJk
systemd-private-1516b7edb3f14f5e82677137397bcc40-vmtoolsd.service-3Rpp62
[root@ying02 ~]# + for ip in '`cat /tmp/ip.list`'
+ echo 192.168.112.139
192.168.112.139
+ ./exe.expect 192.168.112.139 'w;free -m;ls /tmp'
spawn ssh root@192.168.112.139
root@192.168.112.139's password: 
Last login: Fri Aug  3 01:05:47 2018 from 192.168.112.136
[root@ying03 ~]# w;free -m;ls /tmp                                             //ying03下 
 01:09:25 up  1:21,  2 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.112.1    23:52   38:05   0.03s  0.03s -bash
root     pts/1    192.168.112.136  01:09    0.00s  0.02s  0.00s w
              total        used        free      shared  buff/cache   available
Mem:           1831         121        1571           8         138        1553
Swap:          3813           0        3813
12.txt
systemd-private-e8444e9da4d04018af38aa77476a1a09-chronyd.service-ZpE1xv
systemd-private-e8444e9da4d04018af38aa77476a1a09-vgauthd.service-fniGRJ
systemd-private-e8444e9da4d04018af38aa77476a1a09-vmtoolsd.service-r6srcB
[root@ying03 ~]# [root@ying01 sbin]#
相关文章
相关标签/搜索