shell编程三

目录

一、分发系统介绍
二、expect脚本远程登录
三、expect脚本远程执行命令
四、expect脚本传递参数
五、expect脚本同步文件
六、expect脚本指定host和要同步的文件
七、构建文件分发系统
八、批量远程执行命令

一、分发系统介绍

  • 场景:
    服务器是LAMP或LNMP环境,运行PHP网站业务。随着业务增长,代码不断迭代,有增加新功能的需求,需要修改代码,但提供服务的机器数量庞大,逐一更新服务器上的代码比较困难。

  • 分发系统介绍
    分发系统的作用是将每段时间更新的代码分别发到服务机器上去,这里使用shell编程脚本实现代码上线(将代码发布到线上环境)。部分开源软件系统也可以实现发布代码到服务器的功能。

  • 上线准备工作及过程
    准备一台模板机器,该机器上的代码是更新后需要上线的代码,使用expect脚本,借助rsync将更新的代码推送到需要上线的机器上。如果需要执行一些命令,可以借助expect登录机器执行命令。

二、expect脚本远程登录

expect是一种能够按照脚本内容里面设定的方式与交互式程序进行“会话”的程序。expect可以知道程序会提示或反馈什么内容以及什么是正确的应答。它是一种可以提供“分支和嵌套结构”来引导程序流程的解释型脚本语言。另外,还可以在随时需要的时候把控制权交给用户,然后再还给脚本。

  • 安装expect
#若未安装则使用yum安装
[root@minglinux-01 ~] yum install -y expect
  • expect实现远程登录脚本
[root@minglinux-01 /usr/local/sbin] vim 1.expect

  1 #!/usr/bin/expect   
  2 set host "192.168.162.132"   #set 变量名 定义变量
  3 set passwd "123456"   #
  4 spawn ssh root@$host  #
  5 expect {   #用户交互
  6 "yes/no"{ send "yes\r";exp_continue }  #截取输出内容,当输出的内容包含yes/no时,发送yes并回车(初次登录时的情景),\r表示回车,exp_continue表示继续
  7 "password: " { send "$passwd\r" }  #继续发送密码
  8 }
  9 interact #Interact表示停留在远程机器上等待交互不退出
#expect eof则会在远程机器上停留一两秒后再退出
#不加第九行interact会马上退出远程机器
  • 测试expect脚本
[root@minglinux-01 /usr/local/sbin] chmod a+x 1.expect  #增加权限
#清除内容恢复"yes/no"提示
[root@minglinux-01 /usr/local/sbin] vim /root/.ssh/known_hosts   
[root@minglinux-01 /usr/local/sbin] ./1.expect 
spawn ssh root@192.168.162.132
The authenticity of host '192.168.162.132 (192.168.162.132)' can't be established.
ECDSA key fingerprint is SHA256:iqL2TD9uuoPLw0iBc4CDeg2rwceB4m5w79eFoE94zWo.
ECDSA key fingerprint is MD5:5b:95:6c:f7:1b:4d:84:5e:66:0d:b1:fa:a7:e2:4e:d6.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.162.132' (ECDSA) to the list of known hosts.
root@192.168.162.132's password: 
Last login: Mon Jan 14 17:16:31 2019 from 192.168.162.130
[root@minglinux-02 ~]

三、expect脚本远程执行命令

#minglinux-01上执行
[root@minglinux-01 /usr/local/sbin] vim 2.expect

  1 #!/usr/bin/expect
  2 set user "root"
  3 set passwd "123456"
  4 spawn ssh $user@192.168.162.132
  5 
  6 expect {
  7 "yes/no" { send "yes\r"; exp_continue}
  8 "password:" { send "$passwd\r" }
  9 }
 10 expect "]*"  #当匹配到"]*"字符时执行以下命令,"*"表通配
 11 send "touch /tmp/expect.txt\r"
 12 expect "]*"
 13 send "echo hellohello > /tmp/expect.txt\r"
 14 expect "]*"
 15 send "exit\r"  #直接退出远程机器

[root@minglinux-01 /usr/local/sbin] chmod a+x 2.expect 
[root@minglinux-01 /usr/local/sbin] ./2.expect 
spawn ssh root@192.168.162.132
root@192.168.162.132's password: 
Last login: Mon Jan 14 21:39:24 2019 from 192.168.162.1
[root@minglinux-02 ~] touch /tmp/expect.txt
[root@minglinux-02 ~] echo hellohello > /tmp/expect.txt

##minglinux-02上执行
[root@minglinux-02 /tmp] cat expect.txt 
hellohello

四、expect脚本传递参数

[root@minglinux-01 /usr/local/sbin] vim 3.expect

  1 #!/usr/bin/expect
  2 
  3 set user [lindex $argv 0] #将第一个参数传递给变量user
  4 set host [lindex $argv 1] #将第二个参数传递给变量host
  5 set passwd "123456"
  6 set cm [lindex $argv 2] #将第三个变量传递给cm
  7 spawn ssh $user@$host
  8 
  9 expect { 
 10 "yes/no" { send "yes\r"}
 11 "password:" { send "$passwd\r" }
 12 }
 13 expect "]*"
 14 send "$cm\r"
 15 expect "]*"
 16 send "exit\r"
#执行3.expect
[root@minglinux-01 /usr/local/sbin] chmod a+x 3.expect 
[root@minglinux-01 /usr/local/sbin] ./3.expect root 192.168.162.132 ls
spawn ssh root@192.168.162.132
root@192.168.162.132's password: 
Last login: Mon Jan 14 22:02:12 2019 from 192.168.162.130
[root@minglinux-02 ~] ls
anaconda-ks.cfg             SIMLI.TTF
a.txt                       zabbix-release-3.2-1.el7.noarch.rpm
jdk-8u191-linux-x64.tar.gz
#执行多个命令
[root@minglinux-01 /usr/local/sbin] ./3.expect root 192.168.162.132 "ls;w;vmstat 1"
spawn ssh root@192.168.162.132
root@192.168.162.132's password: 
Last login: Mon Jan 14 22:25:19 2019 from 192.168.162.130
[root@minglinux-02 ~] ls;w;vmstat 1
anaconda-ks.cfg             SIMLI.TTF
a.txt                       zabbix-release-3.2-1.el7.noarch.rpm
jdk-8u191-linux-x64.tar.gz
 22:28:07 up 1 day, 18:09,  4 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.162.1    15:58    5:20m  0.03s  0.03s -bash
root     pts/1    192.168.162.1    21:39   21:11   0.04s  0.04s -bash
root     pts/2    192.168.162.130  17:19    5:09m  0.02s  0.02s -bash
root     pts/3    192.168.162.130  22:28    0.00s  0.02s  0.02s w
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 592460   2076 664988    0    0     1    11   52   54  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0   99   93  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0   88   84  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0  119  111  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0   99   91  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0   98   88  0  1 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0  113   99  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0   98   93  0  1 100  0  0
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in   cs us sy id wa st
 1  0      0 592528   2076 665060    0    0     0     0   89   83  0  0 100  0  0
 0  0      0 592528   2076 665060    0    0     0     0  100   96  0  0 100  0  0
##在expect中存在超时时间(大约10s),不适合运行需要长时间执行的命令如vmstat

五、expect脚本同步文件

[root@minglinux-01 /usr/local/sbin] vim 4.expect

  1 #!/usr/bin/expect
  2 set passwd "123456"
  3 spawn rsync -av root@192.168.162.132:/tmp/expect.txt /tmp/
  4 expect {
  5 "yes/no" { send "yes\r"}
  6 "password:" { send "$passwd\r" }
  7 }
  8 expect eof #若无expect eof则rsync还未来得及传输文件就被退出终端
#使用set timeout设置超时时间,
#如set timeout 5设置超时时间为5s,
#set timeout -1设置超时时间为永不超时。
 

[root@minglinux-01 /usr/local/sbin] chmod a+x 4.expect
[root@minglinux-01 /usr/local/sbin] ./4.expect 
spawn rsync -av root@192.168.162.132:/tmp/expect.txt /tmp/
root@192.168.162.132's password: 
receiving incremental file list
expect.txt

sent 43 bytes  received 106 bytes  99.33 bytes/sec
total size is 11  speedup is 0.07
[root@minglinux-01 /usr/local/sbin] ls /tmp/expect.txt 
/tmp/expect.txt

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

#从本机同步到对方
[root@minglinux-01 /usr/local/sbin] vim 5.expect
#脚本内容,此方式只能同步一个文件或者目录
  1 #!/usr/bin/expect
  2 set passwd "123456"
  3 set host [lindex $argv 0]
  4 set file [lindex $argv 1]
  5 spawn rsync -av $file root@$host:$file
  6 expect {
  7 "yes/no" { send "yes\r"}
  8 "password:" { send "$passwd\r" }
  9 }
 10 expect eof

[root@minglinux-01 /usr/local/sbin] chmod a+x 5.expect 
[root@minglinux-01 /usr/local/sbin] ./5.expect 192.168.162.132 "/tmp/expect.txt"
spawn rsync -av /tmp/expect.txt root@192.168.162.132:/tmp/expect.txt
root@192.168.162.132's password: 
sending incremental file list

sent 48 bytes  received 12 bytes  120.00 bytes/sec
total size is 11  speedup is 0.18

七、构建文件分发系统

  • 需求背景:
    对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
  • 思路:
    需要有一台模板机器,准备好要分发的文件,使用expect脚本批量将需要同步的文件分发到目标机器。
  • 核心命令:
    rsync -av –files-from=list.txt / root@host:/
#用于同步文件的rsync.expect 脚本文件内容
[root@minglinux-01 /usr/local/sbin] vim rsync.expect

  1 #!/usr/bin/expect
  2 set passwd "123456"  #考虑安全性可使用密钥认证
  3 set host [lindex $argv 0]
  4 set file [lindex $argv 1]
  5 spawn rsync -avR --files-from=$file / root@$host:/ #加R参数,此时若目标机器不存在同步的目录时会自动创建级联目录
  6 expect {
  7 "yes/no" { send "yes\r"}
  8 "password:" { send "$passwd\r" }
  9 }
 10 expect eof
#创建文件路径的列表文件
[root@minglinux-01 /usr/local/sbin] vim file.list

  1 /root/root.txt
  2 /tmp/2018.txt
#创建相关文件
[root@minglinux-01 /usr/local/sbin] touch /root.txt
[root@minglinux-01 /usr/local/sbin] touch /tmp/2018.txt
#创建主机IP列表文件
[root@minglinux-01 /usr/local/sbin] vim ip.list

  1 192.168.162.132
#创建用于遍历ip列表的脚本rsync.sh
[root@minglinux-01 /usr/local/sbin] vim rsync.sh

  1 #!/bin/bash
  1 #!/bin/bash
  2 for ip in `cat ip.list`
  3 do
  4     echo $ip
  5     ./rsync.expect $ip file.list
  6 done
#执行脚本
[root@minglinux-01 /usr/local/sbin] chmod a+x rsync.expect
[root@minglinux-01 /usr/local/sbin] chmod a+x rsync.sh
[root@minglinux-01 /usr/local/sbin] sh rsync.sh 
192.168.162.132
spawn rsync -avR --files-from=file.list / root@192.168.162.132:/
root@192.168.162.132's password: 
building file list ... done
root/
root/root.txt
tmp/
tmp/2018.txt

sent 200 bytes  received 60 bytes  173.33 bytes/sec
total size is 0  speedup is 0.00

#查看目标主机
[root@minglinux-02 ~] ls /root/root.txt
/root/root.txt
[root@minglinux-02 ~] ls /tmp/2018.txt
/tmp/2018.txt

八、批量远程执行命令

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

  • 创建exe.expect内容如下

[root@minglinux-01 /usr/local/sbin] vim exe.expect

  1 #!/usr/bin/expect
  2 set host [lindex $argv 0]
  3 set passwd "123456"
  4 set cm [lindex $argv 1]
  5 spawn ssh root@$host
  6 expect {
  7 "yes/no" { send "yes\r"}
  8 "password:" { send "$passwd\r" }
  9 }
 10 expect "]*"
 11 send "$cm\r"
 12 expect "]*"
 13 send "exit\r"
  • 创建 exe.sh内容如下
[root@minglinux-01 /usr/local/sbin] vim exe.sh

  1 #!/bin/bash
  2 for ip in `cat ip.list`
  3 do
  4     echo $ip
  5     ./exe.expect $ip "w;free -m;ls /tmp"
  6 done
  • 执行脚本
[root@minglinux-01 /usr/local/sbin] chmod a+x exe.expect 
[root@minglinux-01 /usr/local/sbin] sh exe.sh 
192.168.162.132
spawn ssh root@192.168.162.132
root@192.168.162.132's password: 
Last login: Wed Jan 16 22:27:12 2019 from 192.168.162.130
[root@minglinux-02 ~] w;free -m;ls /tmp
 22:27:32 up 1 day, 22:48,  3 users,  load average: 0.00, 0.01, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.162.1    22:15   11:57   0.01s  0.01s -bash
root     pts/1    192.168.162.130  22:27    0.00s  0.00s  0.00s w
root     pts/3    192.168.162.1    二16   28:31m  0.05s  0.05s -bash
              total        used        free      shared  buff/cache   available
Mem:           1821         589         580           9         652        1047
Swap:          2047           0        2047
2018.txt
331601950@qq.com
expect.txt
mysql.sock
systemd-private-6e247fb2b41e4891b7f0ef4e53aae16d-nginx.service-CC0cwz
vmware-root
yum_save_tx.2018-12-21.16-22.lJigJq.yumtx
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,635评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,628评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,971评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,986评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,006评论 6 394
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,784评论 1 307
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,475评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,364评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,860评论 1 317
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,008评论 3 338
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,152评论 1 351
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,829评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,490评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,035评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,156评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,428评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,127评论 2 356

推荐阅读更多精彩内容