shell项目-分发系统-expect

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

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

二、远程登录

2.1 环境需求

  • 模板机
  • 线上的server

2.2 模板机配置

[root@zhdy-03 ~]#  yum install -y expect

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

vim main.expect

#! /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核心语法,也许会有疑问,如下图:

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

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

2.4 授权

[[email protected]-03 sbin]# chmod a+x main.expect

2.5 连接运行脚本

[[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

#!/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"
[[email protected]-03 sbin]# chmod a+x main2.expect

3.2 脚本分析:

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

3.3 执行效果如下:

[[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去查看下是否已经创建了文件呢?

[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

#!/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 授权

[[email protected]-03 sbin]# chmod a+x main3.expect

4.3 执行测试

[[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秒钟,如何让他不限时间呢?

#!/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秒就自动退出

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

[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服务。

#!/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 授权并测试

[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

#!/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 授权

[[email protected]-03 sbin]# chmod a+x main5.expect

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

[[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 执行

[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 去远程服务器上查看

[[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脚本批量把需要同步的文件分发到目标机器即可。

核心命令:

rsync -av --files-from=list.txt / [email protected]t:/

7.2 脚本配置

#!/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当中去定义 哪些目录或文件是我们需要同步更新上线的。

授权:

[[email protected]-03 sbin]# chmod a+x rsync.expect
[[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

[[email protected]-03 sbin]# vim /tmp/ip.list

192.168.59.132
127.0.0.1

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

"password:" { send "$passwd\r" }

7.3 创建一个rsync的shell

[[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 执行测试

[[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

#!/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 授权

[[email protected]-03 sbin]# chmod a+x exe.expect

8.3 定义exe的shell脚本

vim exe.sh

#!/bin/bash
for ip in `cat ip.list`
do
    echo $ip
    ./exe.expect $ip "w;free -m;ls /tmp"
done

8.3 执行检测

[[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,并且执行了相关的命令!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Java技术栈

SpringCloud动态刷新配置信息

有时候在配置中心有些参数是需要修改的,这时候如何不重启而达到实时生效的效果呢? 添加依赖 <dependencies> ... <depende...

30950
来自专栏芋道源码1024

注册中心 Eureka 源码解析 —— Eureka-Server 启动(一)之 ServerConfig

本文主要基于 Eureka 1.8.X 版本 1. 概述 2. EurekaServerConfig 2.1 类关系图 2.2 配置属性 2.3 Default...

39750
来自专栏编程坑太多

python多版本共存最好的解决方案-虚拟环境

18240
来自专栏Python

linux每日命令(29):chown命令

chown将指定文件的拥有者改为指定的用户或组,用户可以是用户名或者用户ID;组可以是组名或者组ID;文件是以空格分开的要改变权限的文件列表,支持通配符。系统管...

23040
来自专栏java沉淀

build.xml: 33: Class not found: javac1.8的解决办法

19330
来自专栏云计算教程系列

​如何使用Nginx反向代理配置SSL加密的Jenkins

默认情况下,Jenkins自带内置的Winstone网络服务器,可以通过8080端口进行监听,方便入门。但是,只要您认真使用Jenkins,就应该使用SSL保护...

31940
来自专栏大魏分享(微信公众号:david-share)

Howdy,China!:构建JSF Web Application第一篇

版权说明:本文书写过程中参照了红帽的技术文档;本系列文章中的部分测试代码为红帽公司版权所有,因此不能提供源码文件。

12920
来自专栏北京马哥教育

详细到没朋友,一文帮你理清Linux 用户与用户组关系~

15230
来自专栏CodeSheep的技术分享

Spring Boot日志框架实践

23570
来自专栏用户画像

Jboss安装

 1、下载http://pan.baidu.com/s/1bnmYN7p,解压jboss-as-7.1.1.Final.zip即完成安装

14030

扫码关注云+社区

领取腾讯云代金券