前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >shell项目-分发系统-expect

shell项目-分发系统-expect

作者头像
老七Linux
发布2018-05-09 16:51:04
1.4K0
发布2018-05-09 16:51:04
举报
文章被收录于专栏:Laoqi's Linux运维专列

一、什么是分发系统?(循序渐进)

服务上线,这个词应该不陌生,公司内部一般都会有很多服务器,随着业务的不断发展,我们需要不断的去调整服务器的各项配置来适配现在的需求,但是server很多不可能一台一台的去修改,浪费人工和时间,这时候我们需要一个系统,这个系统可以帮助我们把更新的配置更新到每台服务器。

二、远程登录

2.1 环境需求

  • 模板机
  • 线上的server

2.2 模板机配置

代码语言:javascript
复制
[root@zhdy-03 ~]#  yum install -y expect

2.3 自动远程登录,执行命令

vim main.expect

代码语言:javascript
复制
#! /usr/bin/expect
set host "192.168.59.132"
set passwd "123456"
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"; exp_continue}
"assword:" { send "$passwd\r" }
}
interact

关于expect核心语法,也许会有疑问,如下图:

mark
mark

当遇到如上第一次连接需要确认的时候,直接yes \r是回车的意思,然后继续,再次输入密码,这个地方的密码就是上面定义的对方server的密码。

注意以上格式,和我们正常使用的shell是不一样的语法!

2.4 授权

代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x main.expect

2.5 连接运行脚本

代码语言:javascript
复制
[[email protected]-03 sbin]# ./main.expect 
spawn ssh [email protected]192.168.59.132
The authenticity of host '192.168.59.132 (192.168.59.132)' can't be established.
ECDSA key fingerprint is d3:ff:16:8c:ae:78:c5:54:01:35:01:e4:b6:34:cc:f7.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.59.132' (ECDSA) to the list of known hosts.
[email protected]192.168.59.132's password: 
Last login: Wed Sep 20 17:13:47 2017 from 192.168.59.1
[[email protected]-04 ~]#

这样就轻松的连接到了对方的server。

三、脚本远程执行命令 (自动远程登录后,执行命令并退出 )

3.1 在理解刚刚脚本的基础上,再次提升脚本的功能:

vim main2.expect

代码语言:javascript
复制
#!/usr/bin/expect
set user "root"
set passwd "123456"
spawn ssh $user@192.168.59.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"
代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x main2.expect

3.2 脚本分析:

当我们执行成功后,做了一些动作, 创建了touch /tmp/12.txt一个文件,并且在文件内写了一个数据,然后退出远程server。

3.3 执行效果如下:

代码语言:javascript
复制
[[email protected]-03 sbin]# ./main2.expect 
spawn ssh [email protected]192.168.59.132
[email protected]192.168.59.132's password: 
Last failed login: Wed Sep 20 17:42:55 CST 2017 from 192.168.59.131 on ssh:notty
There was 1 failed login attempt since the last successful login.
Last login: Wed Sep 20 17:27:05 2017 from 192.168.59.131
[[email protected]-04 ~]# touch /tmp/12.txt
[[email protected]-04 ~]# echo 1212 > /tmp/12.txt
[[email protected]-04 ~]# [[email protected] sbin]#

最后还是退回到了咱们这台机器。

3.4 检查

我们登录到线上的server去查看下是否已经创建了文件呢?

代码语言:javascript
复制
[root@zhdy-03 sbin]# ./main.expect 
spawn ssh root@192.168.59.132
root@192.168.59.132's password: 
Last login: Wed Sep 20 17:43:27 2017 from 192.168.59.131
[root@zhdy-04 ~]# ls /tmp/
12.txt      sh-thd-1505201881
[root@zhdy-04 tmp]# cat 12.txt 
1212

四、脚本传递参数

4.1 脚本参数设置

vim main3.expect

代码语言:javascript
复制
#!/usr/bin/expect

set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "123456"
set cm [lindex $argv 2]
spawn ssh [email protected]$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

脚本中的 $argv 0 或者 $argv 1 就是所谓的执行脚本时候所输入的第一个第二个参数。

4.2 授权

代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x main3.expect

4.3 执行测试

代码语言:javascript
复制
[[email protected] sbin]# ./main3.expect root 192.168.59.132 ls
spawn ssh [email protected]192.168.59.132
[email protected]192.168.59.132's password: 
Last login: Wed Sep 20 17:45:21 2017 from 192.168.59.131
[[email protected] ~]# ls
anaconda-ks.cfg  sendEmail-v1.56         zabbix-release-3.2-1.el7.noarch.rpm
awk              sendEmail-v1.56.tar.gz  zabbix-release-3.2-1.el7.noarch.rpm.1

执行后不难发现,第一个参数就是user,第二个是主机host,第三个就是需要执行的命令。

补充:

脚本在执行的时候会执行远程命令默认是10秒钟,如何让他不限时间呢?

代码语言:javascript
复制
#!/usr/bin/expect

set user [lindex $argv 0]
set host [lindex $argv 1]
set passwd "123456"
set cm [lindex $argv 2]
spawn ssh [email protected]$host

expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
set timeout -1
expect "]*"
send "exit\r"

也就是说我们只需要添加set timeout -1即可! 当然也可以设置不同的秒,set timeout 5 意味着5秒就自动退出

当然也可以同时执行多个命令:

代码语言:javascript
复制
[root@zhdy-03 sbin]# ./main3.expect root 192.168.59.132 "ls;w;vmstat 1 2"
spawn ssh root@192.168.59.132
root@192.168.59.132's password: 
Last login: Wed Sep 20 18:01:28 2017 from 192.168.59.131
[root@zhdy-04 ~]# ls;w;vmstat 1 2
anaconda-ks.cfg  sendEmail-v1.56         zabbix-release-3.2-1.el7.noarch.rpm
awk              sendEmail-v1.56.tar.gz  zabbix-release-3.2-1.el7.noarch.rpm.1
 18:04:07 up 51 min,  2 users,  load average: 0.01, 0.06, 0.06
USER     TTY      FROM             [email protected]   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.59.1     17:13   37:59   0.07s  0.07s -bash
root     pts/1    192.168.59.131   18:04    0.00s  0.01s  0.00s w
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 206580    876 200056    0    0    54    49   83  187  0  0 98  1  0
 0  0      0 206580    876 200080    0    0     0     0   53  114  0  0 100  0  0
[root@zhdy-04 ~]# [root@zhdy-03 sbin]#

如上不难发现,已经正常的登录,并且执行了我们所需要的命令参数。

五、自动同步文件

5.1 配置脚本

核心命令,就是用的rsync服务。

代码语言:javascript
复制
#!/usr/bin/expect
set passwd "123456"
spawn rsync -av [email protected]:/tmp/12.txt /tmp/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

5.2 授权并测试

代码语言:javascript
复制
[root@zhdy-03 sbin]# chmod a+x main4.expect 

[root@zhdy-03 sbin]# ./main4.expect 
spawn rsync -av root@192.168.59.132:/tmp/12.txt /tmp/
root@192.168.59.132's password: 
receiving incremental file list
12.txt

sent 36 bytes  received 84 bytes  80.00 bytes/sec
total size is 5  speedup is 0.04

如上可以看出 已经成功的同步了文件。

expect eof 脚本中,如果我们不加此语句,一旦登录成功就退出。

六、指定host和要同步的文件

6.1 脚本配置

vim main5.expect

代码语言:javascript
复制
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -av $file [email protected]$host:$file
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

脚本主要意思是:推送一个本地文件到远程服务器。

6.2 授权

代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x main5.expect

我现在尝试吧我本地的一个文件推送到服务器:文件内容如下:

代码语言:javascript
复制
[[email protected] sbin]# cat /tmp/users.txt 
username: user_9 password: 1zg^NIx7on
username: user_5 password: e21oHjeYg=
username: user_6 password: e21oHjeYg=
username: user_7 password: e21oHjeYg=
username: user_8 password: e21oHjeYg=
username: user_5 password: gNR0o{1qjw
username: user_6 password: Pam1lxsN6[
username: user_7 password: 6hd5p^XgwM
username: user_8 password: kvcoyJ5_G0
username: user_5 password: is0wb*SNj7
username: user_6 password: BEgg89qgz<
username: user_7 password: Nxvt8-xGw8
username: user_8 password: 6mpbk5sDS-

6.3 执行

代码语言:javascript
复制
[root@zhdy-03 sbin]# ./main5.expect 192.168.59.132 "/tmp/users.txt"
spawn rsync -av /tmp/users.txt root@192.168.59.132:/tmp/users.txt
root@192.168.59.132's password: 
sending incremental file list
users.txt

sent 571 bytes  received 31 bytes  1204.00 bytes/sec
total size is 494  speedup is 0.82

6.4 去远程服务器上查看

代码语言:javascript
复制
[[email protected] ~]# cat /tmp/users.txt 
username: user_9 password: 1zg^NIx7on
username: user_5 password: e21oHjeYg=
username: user_6 password: e21oHjeYg=
username: user_7 password: e21oHjeYg=
username: user_8 password: e21oHjeYg=
username: user_5 password: gNR0o{1qjw
username: user_6 password: Pam1lxsN6[
username: user_7 password: 6hd5p^XgwM
username: user_8 password: kvcoyJ5_G0
username: user_5 password: is0wb*SNj7
username: user_6 password: BEgg89qgz<
username: user_7 password: Nxvt8-xGw8
username: user_8 password: 6mpbk5sDS-

已经成功推送!!!

但是这只是开始,一般我们推送一个软件或者上线一个服务肯定不是一个文件就可以的。所以我们需要的是大量的文件子目录+脚本推送。

七、文件分发系统实现

7.1 需求背景

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

实现思路:

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

核心命令:

代码语言:javascript
复制
rsync -av --files-from=list.txt / [email protected]t:/

7.2 脚本配置

代码语言:javascript
复制
#!/usr/bin/expect
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
spawn rsync -avR --files-from=$file / [email protected]$host:/
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect eof

rsync -av –files-from=$file / [email protected]$host:/:上传文件的列表是$file,我们需要在list当中去定义 哪些目录或文件是我们需要同步更新上线的。

授权:

代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x rsync.expect
代码语言:javascript
复制
[[email protected]03 sbin]# vim /tmp/list.txt

/tmp/12.txt
/usr/local/sbin/23.sh
/tmp/disk.txt

假如我们需要同步如上3个文件,前提是一定要保证对方的server一定也要有这个目录,例如: /tmp/ /user/local/sbin/ /tmp/, 不然同步会出错。(如上脚本中我们添加了 rsync -avR R就是自动创建级联的目录。)

一般我们代码上线肯定不是针对一台机器来操作的,所以我们也需要定义ip list

代码语言:javascript
复制
[[email protected]-03 sbin]# vim /tmp/ip.list

192.168.59.132
127.0.0.1

还有一个重要的前提就是:所有的机器必须要保证有着相同的密码。但是这样操作有点危险,一旦文档泄露就比较麻烦了。所以我们会选择针对需要同步的服务器进行密钥认证。一旦密钥认证后,如下脚本中的语句我们就可以省略:

代码语言:javascript
复制
"password:" { send "$passwd\r" }

7.3 创建一个rsync的shell

代码语言:javascript
复制
[[email protected] sbin]# vim rsync.sh

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

此脚本的目的就是遍历所有的server和list中的文件可以同步到每台服务器。

7.4 执行测试

代码语言:javascript
复制
[[email protected] sbin]# sh -x rsync.sh 
++ cat /tmp/ip.list
+ for ip in '`cat /tmp/ip.list`'
+ echo 192.168.59.132
192.168.59.132
+ ./rsync.expect 192.168.59.132 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/
[email protected]'s password: 
building file list ... done
home/
home/user_00/
home/user_00/.bashrc
tmp/
usr/local/
usr/local/sbin/
usr/local/sbin/1.txt

sent 553 bytes  received 65 bytes  1236.00 bytes/sec
total size is 250  speedup is 0.40
+ for ip in '`cat /tmp/ip.list`'
+ echo 127.0.0.1
127.0.0.1
+ ./rsync.expect 127.0.0.1 /tmp/list.txt
spawn rsync -avR --files-from=/tmp/list.txt / [email protected]:/
[email protected]'s password: 
building file list ... done

sent 207 bytes  received 12 bytes  438.00 bytes/sec
total size is 250  speedup is 1.14

八、批量远程执行命令

有时候当我们传输同步完毕之后,可能需要重启一下nginx服务,或者mysql服务,这样就用到了远程执行命令。

8.1 脚本配置

vim exe.expect

代码语言:javascript
复制
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
set cm [lindex $argv 1]
spawn ssh [email protected]$host
expect {
"yes/no" { send "yes\r"}
"password:" { send "$passwd\r" }
}
expect "]*"
send "$cm\r"
expect "]*"
send "exit\r"

set host [lindex $argv 0]:第一个参数

set cm [lindex $argv 1]:第二个参数

8.2 授权

代码语言:javascript
复制
[[email protected]-03 sbin]# chmod a+x exe.expect

8.3 定义exe的shell脚本

vim exe.sh

代码语言:javascript
复制
#!/bin/bash
for ip in `cat ip.list`
do
    echo $ip
    ./exe.expect $ip "w;free -m;ls /tmp"
done

8.3 执行检测

代码语言:javascript
复制
[[email protected]03 sbin]# sh exe.sh 
192.168.96.130
spawn ssh [email protected]192.168.96.130
Last login: Fri Sep 22 00:20:41 2017 from 192.168.96.1
                                  _oo0oo_
                                 088888880
                                 88" . "88
                                 (| -_- |)
                                  0\ = /0
                               ___/'---'\___
                             .' \\\\|     |// '.
                            / \\\\|||  :  |||//\\
                           /_ ||||| -:- |||||-  \\
                          |   | \\\\\\  -  /// | |
                          | \_|  ''\---/''  |_/  |
                          \  .-\__  '-'  __/-.  /
                        ___'. .'  /--.--\  '. .'___
                     ."" '<  '.___\_<|>_/___.' >'  "".
                    | | : '-  \'.;'\ _ /';.'/ - ' : | |
                    \  \ '_.   \_ __\ /__ _/   .-' /  /
                ====='-.____'.___ \_____/___.-'____.-'=====
                                  '=---='
   
   
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                        佛祖保佑    iii    永不死机

[[email protected]04 ~]# w;free -m;ls /tmp
 01:11:44 up 53 min,  2 users,  load average: 0.00, 0.01, 0.03
USER     TTY      FROM             [email protected]   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.96.1     00:20   10:32   0.01s  0.01s -bash
root     pts/1    192.168.96.129   01:11    0.00s  0.00s  0.00s w
              total        used        free      shared  buff/cache   available
Mem:            976          85         758           6         132         740
Swap:          2047           0        2047
systemd-private-0a7ea94bd4d44c118420e4eb27a12be4-vmtoolsd.service-dwg4H7

已经成功登陆到了定义的远程server,并且执行了相关的命令!

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016/09/20,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档