【小项目】使用shell和expect实现简易的文件分发系统
分发系统介绍
所谓分发系统就是一个主要用来上线代码或同步文件的脚本,先来看一下需求背景:
- 我们的一个网站在很多台服务器上跑着,假设这个网站的后端是使用PHP编写的,那么当这个后端的PHP代码需要更新或扩展的时候,要如何将这些更新、扩展的代码全部都发布到这些服务器上?
所以分发系统就是用来完成以上这个需求的,分发系统需要完成的事情就是将需要上线的代码分发到这些线上服务器中。我们现在要做的就是实现这个分发系统,实现这个系统需要用到两个主要的东西就是shell和expect,通过shell结合expect可以编写一个简单的分发系统。
<br>
构建文件分发系统
- 需求背景: 对于大公司而言,肯定时不时会有网站或者配置文件更新,而且使用的机器肯定也是好多台,少则几台,多则几十甚至上百台。所以,自动同步文件是至关重要的。
- 实现思路: 首先要有一台模板机器,把要分发的文件准备好,然后只要使用expect脚本批量把需要同步的文件分发到目标机器即可。
- 核心命令: rsync -av --files-from=list.txt / root@host:/
文件分发系统的实现: 1.使用expect编写一个脚本文件rsync.expect,这个脚本是实现文件同步的脚本,内容如下:
[root@localhost ~/expectFiles]# vim rsync.expect
#!/usr/bin/expect
# 目标机器的登录密码
set passwd "123456"
set host [lindex $argv 0]
set file [lindex $argv 1]
# 核心命令,同步多个文件
spawn rsync -avR --files-from=$file / root@$host:/
expect {
"yes/no" { send "yesr"}
"password:" { send "$passwdr" }
}
expect eof
[root@localhost ~/expectFiles]# chmod a+x rsync.expect
2.然后再编辑一个文本文件,这个文件用来放需要同步的文件列表,例如我这里随便同步几个文件:
[root@localhost ~/expectFiles]# vim /tmp/list.txt
/tmp/12.txt
/root/test.sh
/tmp/test.txt
/root/expectFiles/hostFile.expect
提示:如果你的rsync命令没有加-R选项的话,就需要确保目标机器也有这个文件列表中所定义的目录路径,不然就会报错。
3.还需要编辑一个ip.list,用于存放需要同步的目标机器的IP地址,例如我需要将文件都同步这几个IP的机器上:
[root@localhost ~/expectFiles]# vim /tmp/ip.list
192.168.77.128
192.168.77.130
需要同步的目标机器的密码最好是一致的,因为只是做实验为了简单化就不使用密钥验证了。
4.再编写一个shell脚本rsync.sh,这个脚本比较简单,只是遍历出ip.list文件内容然后交给rsync.expect脚本去执行而已,示例:
[root@localhost ~/expectFiles]# vim rsync.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
# 第二个参数就是需要同步的文件列表
./rsync.expect $ip /tmp/list.txt
done
最后我们只需要执行rsync.sh脚本即可:
[root@localhost ~/expectFiles]# sh rsync.sh
192.168.77.128
spawn rsync -avR --files-from=/tmp/list.txt / root@192.168.77.128:/
root@192.168.77.128's password:
building file list ... done
root/
root/test.sh
root/expectFiles/
root/expectFiles/hostFile.expect
tmp/
tmp/12.txt
tmp/test.txt
sent 666 bytes received 97 bytes 1526.00 bytes/sec
total size is 288 speedup is 0.38
192.168.77.130
spawn rsync -avR --files-from=/tmp/list.txt / root@192.168.77.130.83:/
root@192.168.77.130's password:
building file list ... done
root/
root/test.sh
root/expectFiles/
root/expectFiles/hostFile.expect
tmp/
tmp/12.txt
tmp/test.txt
sent 666 bytes received 97 bytes 1526.00 bytes/sec
total size is 288 speedup is 0.38
[root@localhost ~/expectFiles]#
运行结果如上,没有报错,文件也正常同步了,这样我们就实现了一个很简单的文件分发系统。
<br>
批量远程执行命令
以上我们已经实现了简单的文件分发系统,但是光只能同步文件还不够。因为假设这是网站的后端代码文件,同步完了之后需要重启web服务或者执行一些命令,所以还得再编写一个能够批量远程执行命令的脚本。
1.同样的先使用expect编写远程登录的脚本文件exe.expect, 内容如下:
[root@localhost ~/expectFiles]# vim exe.expect
#!/usr/bin/expect
set host [lindex $argv 0]
set passwd "123456"
set cm [lindex $argv 1]
spawn ssh root@$host
expect {
"yes/no" { send "yesr"}
"password:" { send "$passwdr" }
}
expect "]*"
send "$cmr"
expect "]*"
send "exitr"
[root@localhost ~/expectFiles]# chmod a+x exe.expect
2.除此之外还需要写一个shell脚本exe.sh,这个脚本和rsync.sh差不多都是遍历出ip.list文件里的ip,内容如下:
[root@localhost ~/expectFiles]# vim exe.sh
#!/bin/bash
for ip in `cat /tmp/ip.list`
do
echo $ip
# 第二个参数就是需要执行的命令
./exe.expect $ip "who;ls"
done
执行exe.sh脚本:
[root@localhost ~/expectFiles]# sh exe.sh
192.168.77.128
spawn ssh root@192.168.77.128
root@192.168.77.128's password:
Last login: Wed Nov 29 21:56:41 2017 from 192.168.77.130
[root@localhost ~]# who;ls
root pts/0 2017-11-29 21:26 (192.168.77.1)
root pts/1 2017-11-29 21:57 (192.168.77.130)
mysql57-community-release-el7-8.noarch.rpm Test.java
anaconda-ks.cfg stop.sh test.sh
expectFiles Test.class zabbix-release-3.2-1.el7.noarch.rpm
[root@localhost ~]# 192.168.77.130
spawn ssh root@192.168.77.130
root@192.168.77.130's password:
Last login: Thu Nov 30 05:49:18 2017 from 192.168.77.130
[root@localhost ~]# who;ls
root tty1 2017-11-30 05:23
root pts/0 2017-11-30 03:33 (192.168.77.1)
root pts/2 2017-11-30 05:50 (192.168.77.130)
accept_local~ expectFiles grep logs sed shellFile Test test.sh
[root@localhost ~]# [root@localhost ~/expectFiles]#
运行结果如上,没毛病。
done:至此简易的分发系统和批量远程执行命令的功能就完成了。
- 简单的实现Javascript的MVC
- 谷歌再出黑科技!人工智能模拟的人声和真人几乎难以分辨
- 【Scikit-Learn 中文文档】高斯混合模型 - 无监督学习 - 用户指南 | ApacheCN
- “E+单拼”组合域名eqi.com小六位结拍
- ASP.NET Core中的依赖注入(3): 服务的注册与提供
- 【Scikit-Learn 中文文档】使用 scikit-learn 介绍机器学习 | ApacheCN
- 哈萨比斯:2018年AI最大突破在生物或化学领域
- ASP.NET Core中的依赖注入(5): ServiceProvider实现揭秘 【总体设计 】
- ASP.NET MVC的View是如何被呈现出来的?[设计篇]
- Python大牛告诉你一行代码能干什么?神奇
- 谷歌最新人工智能研究:仅利用稀疏轮廓位置“重构”图像
- DATUM和BigchainDB
- MySQL主从复制的实现过程
- 使用dict和set
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法