shell编程(三)

NameVersion
Centos 73.10.0-693.el7.x86_64 #1 SMP Tue Aug 22 21:09:27 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux
expectexpect-5.45-14.el7_1.x86_64

 

分发系统介绍

上线:就是开发的代码发布到线上环境上去。

规范代码上线,使用分发系统(上线的shell脚本)expect(也是一种脚本语言,和shell类似),可以用它实现传输文件远程执行命令,不需输入密码;准备一台模板机器作为准备上线的代码,待发布的所有机器需要知道IP地址和待发布机器用户和密码。使用expect脚本借助rsync把代码推送到待上线机器上去,可以用expect登录这些机器去执行一些命令。

 

expect脚本远程登录

检查是否安装了expect,由于之前用户密码有安装过makepassword就有了expect

  [root@zyshanlinux-001 ~]# yum install -y expect

自动远程登录的expect脚本

  [root@zyshanlinux-001 ~]# vi 1.expect
  #! /usr/bin/expect
  set host "192.168.106.130"
  set passwd "目标机器的登录密码"
  spawn ssh root@$host
  expect {
  "yes/no" { send "yes\r"; exp_continue}
  "password:" { send "$passwd\r" }
  }
  interact

spawn ssh是远程连接,expect { }是核心语句,"yes/no" 和"password:"是截取目标机器的反馈信息;"yes/no"是首次登录才会出现的语句,发现这句,就把"yes\r"发送过去(代表选择yes和回车=\r), exp_continue继续;"password:"则是不是首次登录了,曾经登录过的,则把密码发送过去;interact代表停留在目标机器上,如果把interact改为expect eof则是停留在目标机器上1到2秒,2个都不写的话刚登录上去就马上退出来。

如何把曾经登录的记录清除,变成首次登录;把/root/.ssh/known_hosts文本下把内容全部清除就可以实现。

  [root@zyshanlinux-001 ~]# ssh 192.168.106.130
  root@192.168.106.130's password:
  ​
  [root@zyshanlinux-001 ~]# vi /root/.ssh/known_hosts
  192.168.106.130 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEF7hfCPEDqjB5YyJia4Sv7KxKwu9hPgLHToFvswJX5sCb94mK9E5/MXVeZlzi15swGXR6zHerxAzw5hwtyvpzQ=
  192.168.43.223 ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBCvqX9Y+H3Ngex45gxNgfSI6qzdhFSzNT9npJ1r5x087sNi2AGEhlFfE4HsuOIEGCijYFTzkxtV7WHsz/2LGN2I=

执行1.expect脚本登录目标机器,首先要给1.expect执行权限;执行脚本./1.expect,成功登录目标机器。

  [root@zyshanlinux-001 ~]# chmod a+x 1.expect 
  [root@zyshanlinux-001 ~]# ./1.expect 
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Sat Jul 28 12:15:28 2018 from 192.168.106.1
  [root@zyshanlinux-02 ~]# 

 

expect脚本远程执行命令

自动远程登录后,执行命令并退出

  [root@zyshanlinux-02 ~]# logout
  Connection to 192.168.106.130 closed.
  [root@zyshanlinux-001 ~]# vi 2.expect
  #!/usr/bin/expect
  set user "root"
  set passwd "目标机器的登录密码"
  spawn ssh $user@192.168.106.130
  ​
  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"

进入目标机器后,会出现[root@zyshanlinux-02 ~]#或普通用户02 ~]$,所以expect "]*"就是通配出该字符,就执行命令,最后执行完命令,就exit退出。

给予2.expect执行权限,执行就可以看到在目标机器上创建文件并写入数据最后退出该机器。

  [root@zyshanlinux-001 ~]# chmod a+x 2.expect 
  [root@zyshanlinux-001 ~]# ./2.expect 
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 21:35:03 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# touch /tmp/12.txt
  [root@zyshanlinux-02 ~]# echo 1212 > /tmp/12.txt
  [root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]# 
  [root@zyshanlinux-001 ~]# ./1.expect 
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 21:46:55 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# ls -l /tmp/12.txt
  -rw-r--r-- 1 root root 5 8月   2 21:46 /tmp/12.txt
  [root@zyshanlinux-02 ~]# cat !$
  cat /tmp/12.txt
  1212
  [root@zyshanlinux-02 ~]#

 

expect脚本传递参数

传递[lindex $argv 0]、[lindex $argv 1]和[lindex $argv 2]这三个参数,代表用户、IP和命令。

  [root@zyshanlinux-001 ~]# vi 3.expect
  #!/usr/bin/expect
  ​
  set user [lindex $argv 0]
  set host [lindex $argv 1]
  set passwd "目标机器的登录密码"
  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@zyshanlinux-001 ~]# chmod a+x 3.expect
  [root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'ls -l'
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 22:00:38 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# ls -l
  总用量 20
  -rw-------. 1 root root  1418 5月   7 04:27 anaconda-ks.cfg
  -rw-r--r--  1 root root 13392 9月  14 2016 zabbix-release-3.2-1.el7.noarch.rpm
  [root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 "ls -l;w"
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 22:01:03 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# ls -l;w
  总用量 20
  -rw-------. 1 root root  1418 5月   7 04:27 anaconda-ks.cfg
  -rw-r--r--  1 root root 13392 9月  14 2016 zabbix-release-3.2-1.el7.noarch.rpm
   22:03:40 up 48 min,  1 user,  load average: 0.03, 0.06, 0.06
  USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
  root     pts/0    192.168.106.128  22:03    0.00s  0.02s  0.01s w
  [root@zyshanlinux-02 ~]# [root@zyshanlinux-001 ~]#

 

expect脚本同步文件

把目标机器的12.txt利用rsync同步到本机器来。

  [root@zyshanlinux-001 ~]# vi 4.expect
  #!/usr/bin/expect
  set passwd "目标机器的登录密码"
  spawn rsync -av root@192.168.106.130:/tmp/12.txt /tmp/
  expect {
  "yes/no" { send "yes\r"}
  "password:" { send "$passwd\r" }
  }
  expect eof

执行脚本

  [root@zyshanlinux-001 ~]# chmod a+x 4.expect 
  [root@zyshanlinux-001 ~]# ./4.expect 
  spawn rsync -av root@192.168.106.130:/tmp/12.txt /tmp/
  root@192.168.106.130'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
  [root@zyshanlinux-001 ~]# cat /tmp/12.txt
  1212

 

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

设定超时为5秒命令set timeout 5,用命令vmstat 1可以测出超时时间为5秒,5秒后退出该命令,目标机器该命令也没有运行了,因为本地机器已经退出这个shell了所以目标机器的该命令也结束。

  [root@zyshanlinux-001 ~]# vi 3.expect
  #!/usr/bin/expect
  ​
  set user [lindex $argv 0]
  set host [lindex $argv 1]
  set passwd "目标机器的登录密码"
  set cm [lindex $argv 2]
  spawn ssh $user@$host
  ​
  expect {
  "yes/no" { send "yes\r"}
  "password:" { send "$passwd\r" }
  }
  expect "]*"
  send "$cm\r"
  set timeout 5
  expect "]*"
  send "exit\r"
  [root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'vmstat 1'
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 22:23:32 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# vmstat 1
  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 1131600   2076 171300    0    0    37    36  119  142  0  1 99  0  0
   0  0      0 1131108   2076 171340    0    0     0     7  137  150  1  1 98  0  0
   0  0      0 1131108   2076 171340    0    0     0     6  147  152  0  1 99  0  0
   0  0      0 1131108   2076 171344    0    0     0     6  132  146  0  0 100  0  0
   0  0      0 1131076   2076 171344    0    0     0     6  140  151  0  2 98  0  0

把set timeout 5改为set timeout -1就会变为永久不超时。

  [root@zyshanlinux-001 ~]# vi 3.expect
  #!/usr/bin/expect
  ​
  set user [lindex $argv 0]
  set host [lindex $argv 1]
  set passwd "目标机器的登录密码"
  set cm [lindex $argv 2]
  spawn ssh $user@$host
  ​
  expect {
  "yes/no" { send "yes\r"}
  "password:" { send "$passwd\r" }
  }
  expect "]*"
  send "$cm\r"
  set timeout -1
  expect "]*"
  send "exit\r"
  [root@zyshanlinux-001 ~]# ./3.expect root 192.168.106.130 'vmstat 1'
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 22:23:56 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# vmstat 1
  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 1131452   2076 171404    0    0    35    36  118  141  0  1 99  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   81   91  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   77   87  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   82   88  0  0 100  0  0
   1  0      0 1131452   2076 171400    0    0     0     0   80   87  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   77   85  0  1 99  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   81   88  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   84   89  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   78   86  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   81   83  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   81   88  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   81   85  0  1 99  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   80   91  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   80   85  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   80   86  0  0 100  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   79   87  0  1 99  0  0
   0  0      0 1131452   2076 171400    0    0     0     0   80   88  0  0 100  0  0
  ^C[root@zyshanlinux-001 ~]#

把本机器的文件同步到目标机器上去。

  [root@zyshanlinux-001 ~]# vi 5.expect
  #!/usr/bin/expect
  set passwd "目标机器的登录密码"
  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@zyshanlinux-001 ~]# chmod a+x 5.expect 
  [root@zyshanlinux-001 ~]# ./5.expect 192.168.106.130 "/tmp/12.txt"
  spawn rsync -av /tmp/12.txt root@192.168.106.130:/tmp/12.txt
  root@192.168.106.130's password: 
  sending incremental file list
  ​
  sent 45 bytes  received 12 bytes  38.00 bytes/sec
  total size is 5  speedup is 0.09
  [root@zyshanlinux-001 ~]#

 

构建文件分发系统

  • 需求背景

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

  • 实现思路

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

  • 核心命令

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

文件分发系统的实现:

1、rsync.expect 内容,同步时本地机与目标机必须有相同的路径,文件可以没有但目录必须要有;如果没有的话需要加上选项R,同步时级联创建目录路径spawn rsync -avR;所有目标的机器的密码必须一样或者用密钥认证登录。

  vi rsync.expect
  #!/usr/bin/expect
  set passwd "目标机器的登录密码"
  set host [lindex $argv 0]
  set file [lindex $argv 1]
  spawn rsync -av --files-from=$file / root@$host:/
  expect {
  "yes/no" { send "yes\r"}
  "password:" { send "$passwd\r" }
  }
  expect eof

2、ip.list内容,目标机器的IP

  vi /tmp/ip.list
  192.168.106.130
  192.168.43.201

3、rsync.sh内容

  [root@zyshanlinux-001 ~]# vi rsync.sh
  #!/bin/bash
  for ip in `cat /tmp/ip.list`
  do
    echo $ip
    ./rsync.expect $ip /tmp/file.list
  done

4、file.list内容,发布的文件绝对路径

  [root@zyshanlinux-001 ~]# vi /tmp/file.list
  /tmp/12.txt
  /root/13.txt

试验:

  [root@zyshanlinux-001 ~]# chmod a+x rsync.expect
  [root@zyshanlinux-001 ~]# sh -x rsync.sh
  ++ cat /tmp/ip.list
  + for ip in '`cat /tmp/ip.list`'
  + echo 192.168.106.130
  192.168.106.130
  + ./rsync.expect 192.168.106.130 /tmp/file.list
  spawn rsync -avR --files-from=/tmp/file.list / root@192.168.106.130:/
  root@192.168.106.130's password: 
  building file list ... done
  root/
  ​
  sent 121 bytes  received 19 bytes  280.00 bytes/sec
  total size is 5  speedup is 0.04
  + for ip in '`cat /tmp/ip.list`'
  + echo 192.168.43.201
  192.168.43.201
  + ./rsync.expect 192.168.43.201 /tmp/file.list
  spawn rsync -avR --files-from=/tmp/file.list / root@192.168.43.201:/
  root@192.168.43.201's password: 
  Permission denied, please try again.
  root@192.168.43.201's password: [root@zyshanlinux-001 ~]#

 

批量远程执行命令

exe.expect 内容,该文件的后缀没有限定,但文件的内容的头必须是#!/usr/bin/expect,否则无法解析。

  [root@zyshanlinux-001 ~]# vim exe.expect
  #!/usr/bin/expect
  set host [lindex $argv 0]
  set passwd "目标机器的登录密码"
  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"
  [root@zyshanlinux-001 ~]# chmod a+x exe.expect

exe.sh 内容,文件路径要写绝对路径

  [root@zyshanlinux-001 ~]# vi exe.sh
  #!/bin/bash
  for ip in `cat /tmp/ip.list`
  do
      echo $ip
      ./exe.expect $ip 'w;free -m;ls /tmp'
  done

测试

  [root@zyshanlinux-001 ~]# chmod a+x exe.expect
  [root@zyshanlinux-001 ~]# sh -x exe.sh
  ++ cat /tmp/ip.list
  + for ip in '`cat /tmp/ip.list`'
  + echo 192.168.106.130
  192.168.106.130
  + ./exe.expect 192.168.106.130 'w;free -m;ls /tmp'
  spawn ssh root@192.168.106.130
  root@192.168.106.130's password: 
  Last login: Thu Aug  2 22:28:08 2018 from 192.168.106.128
  [root@zyshanlinux-02 ~]# w;free -m;ls /tmp
   23:35:39 up  2:20,  1 user,  load average: 0.00, 0.01, 0.05
  USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
  root     pts/0    192.168.106.128  23:35    0.00s  0.00s  0.00s w
                total        used        free      shared  buff/cache   available
  Mem:           1831         557        1104           8         170        1111
  Swap:          2047           0        2047
  12.txt
  mysql.sock
  systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-chronyd.service-Kng3xS
  systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-vgauthd.service-IVAlr8
  systemd-private-c8c8dddf3f4e4cfd87f2333294c9d88a-vmtoolsd.service-PQVA7o
  [root@zyshanlinux-02 ~]# + for ip in '`cat /tmp/ip.list`'
  + echo 192.168.43.201
  192.168.43.201
  + ./exe.expect 192.168.43.201 'w;free -m;ls /tmp'
  spawn ssh root@192.168.43.201
  root@192.168.43.201's password: 
  Permission denied, please try again.
  root@192.168.43.201's password: 
  Permission denied, please try again.
  root@192.168.43.201's password: [root@zyshanlinux-001 ~]#

 

 

扩展:shell多线程 http://blog.lishiming.net/?p=448

给你提供一本电子书 链接:http://pan.baidu.com/s/1mg49Taw 密码:yk4b

shell习题做一下 http://www.apelearn.com/study_v2/chapter15.html#shll

linux shell命名管道FIFOhttp://blog.lishiming.net/?p=448

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值