20.9 Shell项目——分发系统

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

而要如何实现自动同步呢?首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。整个过程也称为代码上线。


expect脚本远程登录

  • 安装expect:
# yum install -y expect

 

  • 编辑自动远程登录expect脚本:
# vim login.expect				#写入下面内容

 

#! /usr/bin/expectset host "192.168.33.128"				#设置变量set passwd "19940406"				#设置变量spawn ssh root@$hostexpect {"yes/no" { send "yes\r"; exp_continue }"password:" { send "$passwd\r" }}interact				#表示停留在远程机器上,而不需要退出,不加interact会退出

 

  • 执行脚本:
# chmod a+x login.expect				#给予执行权限# ./login.expect				#运行上面的expect脚本spawn ssh root@192.168.33.128
root@192.168.33.128's password: 
Last login: Wed Aug  1 13:41:55 2018 from 192.168.33.1# logout				#已经登录到192.168.33.128上Connection to 192.168.33.128 closed.

 


expect脚本远程登录,执行命令并退出

  • 编辑expect脚本:
# vim login2.expect				#写入下面内容

 

#! /usr/bin/expectset user "root"set passwd "19940406"spawn ssh $user@192.168.33.128expect {"yes/no" { send "yes\r"; exp_continue }"password:" { send "$passwd\r" }}expect "]*"				#不管是root提示符还是普通用户,都匹配到send "touch /tmp/12.txt\r"				#执行命令expect "]*"send "echo 1212 > /tmp/12.txt\r"expect "]*"send "exit\r"

 

  • 执行脚本:
# chmod a+x login2.expect        # ./login2.expect spawn ssh root@192.168.33.128
root@192.168.33.128's password: 
Last login: Wed Aug  1 13:42:03 2018 from 192.168.33.129# touch /tmp/12.txt# echo 1212 > /tmp/12.txt# [root@localhost sbin]#

 


expect脚本传递参数

  • 编辑expect脚本:
# vim login3.expect

 

#! /usr/bin/expectset user [lindex $argv 0]				#第一个参数的值赋给userset host [lindex $argv 1]				#第二个参数的值赋给hostset passwd "19940406"set cm [lindex $argv 2]				#第三个参数的值赋给cm,表示命令spawn ssh $user@$hostexpect {"yes/no" { send "yes\r" }"password:" { send "$passwd\r" }}expect "]*"send "$cm\r"expect "]*"send "exit\r"

 

  • 执行脚本:
# chmod a+x login3.expect # ./login3.expect  root 192.168.33.128 ls				#执行ls命令spawn ssh root@192.168.33.128
root@192.168.33.128's password: 
Last login: Wed Aug  1 14:00:11 2018 from 192.168.33.129

# ls
anaconda-ks.cfg  test.txt  zabbix-release-3.4-2.el7.noarch.rpm

# ./login3.expect root 192.168.33.128 "ls;w;vmstat 1 5"				#可以执行多个命令,expect默认有超时时间,超过时间就会退出
spawn ssh root@192.168.33.128
root@192.168.33.128's password: 
Last login: Wed Aug  1 15:02:44 2018 from 192.168.33.1# ls; w; vmstat 1 5anaconda-ks.cfg  test.txt  zabbix-release-3.4-2.el7.noarch.rpm
 15:06:08 up  1:24,  3 users,  load average: 0.03, 0.02, 0.05
USER     TTY      FROM             LOGIN@   IDLE   JCPU   PCPU WHAT
root     pts/0    192.168.33.1     13:41    1:24m  0.01s  0.01s -bash
root     pts/1    192.168.33.1     15:02    3:24   0.00s  0.00s -bash
root     pts/2    192.168.33.129   15:06    0.00s  0.01s  0.01s 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 2983248   2076 243576    0    0    10    18   48   47  0  0 100  0  0
 0  0      0 2983064   2076 243996    0    0     0     7  219  204  0  0 100  0  0
 0  0      0 2983064   2076 243996    0    0     0   136  181  192  0  0 100  0  0
 0  0      0 2983064   2076 243996    0    0     0     5  165  170  0  0 100  0  0
 0  0      0 2983064   2076 243996    0    0     0     5  205  194  0  0 100  0  0

 


expect脚本同步文件

  • 编辑expect脚本:
# vim login4.expect				#写入下面内容

 

#! /usr/bin/expectset passwd "19940406"spawn rsync -av root@192.168.33.128:/tmp/12.txt /tmp/expect {"yes/no" { send "yes\r" }"password:" { send "$passwd\r" }}expect eof				#表示expect脚本结束,如果不加expect eof会导致还没开始传输就会结束

 

如果想让expect永远不超时,可以在上面添加一行:

set timeout -1				#-1表示永不超时,设置为其它数字就会以其它数字为超时时间,以秒为单位,但是去掉expect eof 仍会出问题

 

  • 执行脚本:
# chmod a+x login4.expect# ./login4.expect spawn rsync -av root@192.168.33.128:/tmp/12.txt /tmp/
root@192.168.33.128's password: 
receiving incremental file list
12.txt

sent 43 bytes  received 97 bytes  280.00 bytes/sec
total size is 5  speedup is 0.04# cat /tmp/12.txt 1212

 


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

  • 编辑expect脚本:
# vim login5.expect				#写入下面内容

 

#! /usr/bin/expectset passwd "19940406"set host [lindex $argv 0]set file [lindex $argv 1]spawn rsync -av $file root@$host:$fileexpect {"yes/no" { send "$yes\r" }"password:" { send "$passwd\r" }}expect eof

 

  • 执行脚本:
# chmod a+x login5.expect# ./login5.expect 192.168.33.128 "/tmp/12.txt"              //将本地文件同步到远程,只适合同时同步一个文件spawn rsync -av /tmp/12.txt root@192.168.33.128:/tmp/12.txt
root@192.168.33.128's password: 
sending incremental file list

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

 

将本地文件同步到远程,只适合同时同步一个文件。


构建文件分发系统

  • 核心命令
rsync -av --files-from=list.txt / root@host:/				#文件路径必须是绝对路径

 

  • 编辑expect脚本:
# vim rsync.expect				#写入下面内容

 

#! /usr/bin/expectset passwd "19940406"set host [lindex $argv 0]set file [lindex $argv 1]				#指的是list.txt ,表示一个列表而不仅仅是一个文件spawn rsync -avR --files-from=$file / root@$host:/expect {"yes/no" { send "yes\r" }"password:" { send "$passwd\r" }}export eof

 

  • 编辑file.list
# vim /tmp/file.list				#写入下面内容/tmp/12.txt
/tmp/1.txt
/tmp/2.txt
/tmp/3.txt
/tmp/111/111.txt

 

  • 编辑ip.list
# vim /tmp/ip.list				#写入下面内容192.168.33.128
127.0.0.1

 

  • 编辑rsync.sh
# vim rsync.sh				#写入下面内容#! /bin/bashfor ip in `cat /tmp/ip.list`do
        ./rsync.expect $ip /tmp/file.listdone

 

  • 执行脚本:
# chmod a+x rsync.expect# sh rsync.shspawn rsync -av --files-from=/tmp/file.list / root@192.168.33.128:/
root@192.168.33.128's password: 
building file list ... done
tmp/
tmp/1.txt
tmp/2.txt
tmp/3.txt
tmp/111/
tmp/111/111.txt/

sent 311 bytes  received 82 bytes  262.00 bytes/sec
total size is 5  speedup is 0.01               //192.168.33.128传输成功
spawn rsync -av --files-from=/tmp/file.list / root@127.0.0.1:/
The authenticity of host '127.0.0.1 (127.0.0.1)' can't be established.				#127.0.0.1出现问题,暂且不用管ECDSA key fingerprint is SHA256:y/jrhxRLVYWO6YhN5a2DSQePmWH3CCVWcV578JDKbPg.
ECDSA key fingerprint is MD5:1b:86:bc:80:c5:c6:14:7a:4f:6c:29:b4:14:8f:86:d1.
Are you sure you want to continue connecting (yes/no)? yesWarning: Permanently added '127.0.0.1' (ECDSA) to the list of known hosts.

 

  • 查看192.168.33.128:
# ls -l /tmp/总用量 4
drwxr-xr-x 3 root  root  21 8月   1 14:47 111
-rw-r--r-- 1 root  root   5 8月   1 14:00 12.txt
-rw-r--r-- 1 root  root   0 8月   1 14:47 1.txt
-rw-r--r-- 1 root  root   0 8月   1 14:47 2.txt
-rw-r--r-- 1 root  root   0 8月   1 14:47 3.txt

 


分发系统命令批量执行

有时候我们在批量传输完文件还不够,还需要在目标机器上执行命令来操作一些服务,这时候就需要对机器进行命令的批量执行。

  • 编辑exe.expect
# vim exe.expect				#写入下面内容

 

#! /usr/bin/expectset host [lindex $argv 0]set passwd "19940406"set cm [lindex $argv 1]spawn ssh root@$hostexpect {"yes/no" { send "yes\r" }"password:" { send "$passwd\r" }}expect "]*"send "$cm\r"expect "]*"send "exit\r"

 

  • 编辑exe.sh
# vim exe.sh				#写入下面内容#! /bin/bashfor ip in `cat /tmp/ip.list`do
        ./exe.expect $ip "hostname"done

 

  • 执行脚本:
# chmod a+x exe.expect # sh exe.sh spawn ssh root@192.168.33.128
root@192.168.33.128's password: 
Last login: Wed Aug  1 15:06:08 2018 from 192.168.33.129

# hostname
localhost.localdomain				#192.168.33.128主机名

# spawn ssh root@127.0.0.1
root@127.0.0.1's password: 
Last failed login: Wed Aug  1 15:17:30 CST 2018 from 127.0.0.1 on ssh:notty
There were 2 failed login attempts since the last successful login.
Last login: Wed Aug  1 13:54:06 2018 from 192.168.33.1# hostnamelocalhost.localdomain				#127.0.0.1本地主机名

 


更多资料参考:

Shell脚本学习之expect命令

linux expect 使用