实验三 文件同步
目录
- 知识准备
- 实验环境
- 实验步骤
- 实验原理与流程图
- 实验内容
- 实验总结
一、 知识准备
1.1 rsync
与传统的cp、tar备份方式相比,rsync具有安全性高、备份迅速、支持增量备份等优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期的备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。
随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出的更好的要求,rsync在高端业务系统中也逐渐暴露出了很多不足,首先,rsync同步数据时,需要扫描所有文件后进行比对,进行差量传输。如果文件数量达到了百万甚至千万量级,扫描所有文件将是非常耗时的。而且正在发生变化的往往是其中很少的一部分,这是非常低效的方式。其次,rsync不能实时的去监测、同步数据,虽然它可以通过linux守护进程的方式进行触发同步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致,无法在应用故障时完全的恢复数据。基于以上原因,rsync+inotify组合出现了!
1.2 inotify
Inotify 是一种强大的、细粒度的、异步的文件系统事件监控机制,linux内核从2.6.13起,加 入了Inotify支持,通过Inotify可以监控文件系统中添加、删除,修改、移动等各种细微事件,利 用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools就是这 样的一个第三方软件。
1.3 MD5
MD5值是一种被广泛使用的bai密码散列函数,可以产du生出一个128位(16字节)的zhi散列值(hash value),用于确保信息dao传输完整一致。
二、 实验环境
两台版本相同的ubuntu虚拟机、两台虚拟机完成了SSH免密登陆、MYSQL的版本相同。
master IP : 192.168.43.132
slave1 IP : 192.168.43.137
三、 实验步骤
1、为两台电脑安装rsync和Inotify
2、设计存MD5值的msyql数据表
3、遍历文件目录并计算其MD5值
4、编写脚本对比新的MD5值与之前的MD5是否变化,并更新数据表
5、加入Inotify技术对文件实时监听
6、rsync实现主从文件同步
7、rsync实现双向文件同步
四、 实验原理与流程图
Inotify实时对同步录进行监听,一旦用户对该目录下的文件进行增删改操做,Inotify就会调用MD5计算算法计算出新的MD5,再与数据库的MD5表进行对比,如果出现差异则更新数据表同时发送同步数据给Slave服务器。Slave服务器接收到同步信息后开始同步文件。
五、 实验内容
5.1 为两台电脑安装rsync和Inotify
# 安装rsync,inotify-tools
$ sudo apt-get install rsync inotify-tools
# 创建同步目录
$ mkdir /linux/bigfile
# 用100000行的文件 bigfile.txt 模拟大文件
5.2 设计存MD5值的msyql数据表
# 设计数据表 MdTable 用于存最近一次同步时间、上次同步的 md5
mysql> create table MdTable (id int(3) auto_increment not null primary key, md5 varchar(200),fixTime datetime);
5.3 遍历文件目录并计算其MD5值
5.3.1 编写脚本遍历 bigfile.txt 文件的 MD5 值
$ cd linux
sudo vi getbigfilemd5.sh#!/bin/bash
# filename : getbigfilemd5.sh
# author : dudu
# time : 2020/10/25
# work : A large file, read only 100 lines at a time, and then each 100 MD5 value, write to the file.record time for generating MD5 values.
# Parameters
i=1
str=
# Delete existing files
rm -f getbigfilemd5.txt
rm -f getbigfiletime.txt
starttime=`date +%Y-%m-%d-%H:%M:%S`
echo “start time = $starttime”
# main
while read line
do
# Recorded every 100 rows
val=`expr KaTeX parse error: Can't use function '\`' in math mode at position 7: i / 10\̲`̲<br><br> *# Ta…{str}${line}"
# MD5 value read per 100 row
if [ $val != 0 ]
then
# Generation time
time=`date +%Y%m%d%H%M%S`
echo KaTeX parse error: Expected 'EOF', got '#' at position 41: …txt<br><br> *#̲ MD5 generated…str"|md5sum|cut -d ’ ’ -f1 >> getbigfilemd5.txt
i=1
str=
fi
i=`expr $i + 1`
done </home/mpi/linux/bigfile/bigfile2.txt
endtime=`date +%Y-%m-%d-%H:%M:%S`
echo “Computational success!”
echo “end time = $endtime”5.3.2 编写脚本遍历计算 整个目录的 MD5 值
$ cd linux
sudo vi getmd5.sh#!/bin/bash
# filename : getmd5.sh
# author : dudu
# time : 2020/10/25
# work : A large file, read only 100 lines at a time, and then each 100 MD5 value, write to the file.record time for generating MD5 values.
# Parameters
i=1
str=
# Delete existing files
rm -f getmd5.txt
rm -f gettime.txt
starttime=`date +%Y-%m-%d-%H:%M:%S`
echo “start time = $starttime”
# main
for f in `ls /home/mpi/linux/file/*`
do
# Generation time
time=`date +%Y%m%d%H%M%S`
echo KaTeX parse error: Expected 'EOF', got '#' at position 34: …txt<br><br> *#̲ MD5 generated…f"|md5sum|cut -d ’ ’ -f1 >> getbigfilemd5.txt
done
endtime=`date +%Y-%m-%d-%H:%M:%S`
echo “Computational success!”
echo “end time = $endtime”5.3.3 测试脚本
$ sudo chmod +x ./getbigfilemd5.sh
$ ./getbigfilemd5.sh
![avatar][base64str7]
$ head -n 10 getbigfilemd5.txt
$ head -n 10 getbigfiletime.txt
注 : 生成的 MD5值存入getbigfilemd5.txt,同步时间存入getbigfiletime.txt 用于效 验 数据库中的 MD5数据表和更新数据表
5.4 编写脚本对比新的MD5值与之前的MD5是否变化,并更新数据表
5.4.1 编写脚本得到新计算的MD5和time集合
$ cd linux
sudo vi work3.sh#!/bin/bash
# filename : work3.sh
# author : dudu
# time : 2020/10/25
# work : Design data sheet (save last synchronization time, last synchronization md5)
# Parameters
newmd5[101]=
newtime[101]=
oldmd5[101]=
oldtime[101]=
flag=0
##### 更新 MD5 数据表 模块
# Update database MD5 table functions
UpdateTable(){
mysql -uroot -proot work3 -e "update MdTable set md5=’ 2 ′ , f i x T i m e = {2}',fixTime= 2′,fixTime={3} where id=KaTeX parse error: Expected 'EOF', got '&' at position 9: 1"<br> &̲nbsp; &nb…line
# echo KaTeX parse error: Expected '}', got 'EOF' at end of input: {newmd5[i]}
# i=`expr KaTeX parse error: Can't use function '\`' in math mode at position 6: i + 1\̲`̲<br> &nb…{line}
# echo ${newtime[$1]}
let j++
# j=`expr $j + 1`
done </home/mpi/linux/getbigfiletime.txt
##### 新老 MD5 和 time 比较功能 模块
# Check that MD5 values change from the database
k=1selectsql="`mysql -uroot -proot work3 -e “select md5 from MdTable;”`"
Select=( s e l e c t s q l ) < b r > l e n = selectsql)<br> len= selectsql)<br>len={#Select[@]}
while [ $k -lt KaTeX parse error: Expected 'EOF', got '&' at position 19: … ]<br> do<br> &̲nbsp; &nb…{Select[$k]}
if [ ! -n KaTeX parse error: Expected '}', got 'EOF' at end of input: {newmd5[k]} ]
then
break
else
if [ KaTeX parse error: Expected '}', got 'EOF' at end of input: {newmd5[k]} != KaTeX parse error: Expected '}', got 'EOF' at end of input: {oldmd5[k]} ]
then
UpdateTable $k KaTeX parse error: Expected '}', got 'EOF' at end of input: {newmd5[k]} KaTeX parse error: Expected '}', got 'EOF' at end of input: {newtime[k]}
flag=1
fi
fi
# echo KaTeX parse error: Expected '}', got 'EOF' at end of input: {newmd5[k]}
let k++
done
##### 发送同步 信息 模块
### Determines whether the MD5 has been changed, and if so, synchronizes
flagPath=/home/mpi/linux
rm -rf $flagPath/flag.txt
echo $flag >> KaTeX parse error: Expected 'EOF', got '#' at position 28: …g.txt<br><br> *#̲ Delete flag fi…flagPath/flag/flag.txt “exit”
# Send synchronization information to the slave
sshpass -p ‘1’ scp flag.txt mpi@slave1:$flagPath/flag
echo " Send messages successfully!!"5.4.2 测试脚本
# 再到 slave1下执行
$ mkdir linux/flag
# 再到 master下执行
$ sudo chmod +x ./getbigfilemd5.sh
# 计算新的 MD5 和 time
$ ./getbigfilemd.sh
![avatar][base64str9]
# 运行 MD5 对比 脚本 并向 slave1 发送同步信息
$ ./work3.sh
![avatar][base64str10]
# 未更新的 MD5 数据表
![avatar][base64str8]
# 比较更新之后的MD5数据表,MD5 变化的部分都得到了更新
![avatar][base64str11]
# slave1 服务器 的 flag.txt 文件存储 master 发送的信息
![avatar][base64str12]
注 : flag.txt文件显示 1 表示 可以执行同步操作 0 表示 不进行同步操作
5.5 加入Inotify技术对文件实时监听
# 使用Inotify技术对 bigfile文件夹进行实时监控,一旦文件发送增删改操作,就会触动getbigfile.sh脚本计算文件新的MD5值和work3.sh脚本比较MD5
5.5.1 master监控 同步目录 bigfile
$ cd linux
$ sudo gedit inotify.sh#!/bin/bash
# filename : inotify.sh
# author : dudu
# time : 2020/10/25
# work :Inotify monitorin g file changes
# Parameters
path=/home/mpi/linux
##### 该模块不需要效验 MD5 值直接发送同步信息
### Direct sending synchronization information to customer service without MD5 inspection
StartSend(){
rm -rf $path/flag.txt
# 1 means start synchronization
echo “0” >> KaTeX parse error: Expected 'EOF', got '&' at position 20: …/flag.txt<br> &̲nbsp; &nb…path/flag/flag.txt “exit”
# Send synchronization information to the slave
sshpass -p ‘1’ scp p a t h / f l a g . t x t m p i @ s l a v e 1 : path/flag.txt mpi@slave1: path/flag.txtmpi@slave1:path/flag
echo " Send messages successfully!!"
}
###### 先调用 MD5 生成 脚本,再调用 MD5 效验 脚本
### MD5 value check before sending synchronous data
CheckMd5(){
# Call MD5 generate scripts
./getbigfilemd5.sh
# Call MD5 validation script
./work3.sh
echo “check successfully!!”
}
### Detect folder changes
inotifywait -mrq --timefmt ‘%y/%m/%d %H:%M’ --format ‘%T %w %f’ -e modify,delete,create,attrib $path/bigfile | while read file
do
# StartSend
CheckMd5
done5.5.2 slave监控 同步信息文件 flag.txt
$ cd linux
$ sudo gedit SlaveInotify.sh#!/bin/bash
# filename : SlaveInotify.sh
# author : dudu
# time : 2020/10/25
# work : Detect changes in flag.txt files and start synchronization with content 1
### Parameters
path=/home/mpi/linux
### Listening Function
inotifywait -mrq --timefmt ‘%y/%m/%d %H:%M’ --format ‘%T %w %f’ -e modify,delete,create,attrib $path/flag | while read file
do
# Synchronization function
echo “Receiving synchronization information”
# StartSy
done5.5.3 测试脚本
# 运行 监听脚本
$ sudo ./inotify.sh
$ sudo ./SlaveInotify.sh
![avatar][base64str14]
# 对 bigfile 目录进行添加操作
$ cd bigfile
$ touch a.txt
# 脚本监听成功
![avatar][base64str13]
# 查看数据库 MD5 表 更新成功
![avatar][base64str15]
查看 slave1 脚本监听情况
![avatar][base64str16]
注 : 监听成功
5.6 rsync实现主从文件同步
5.6.1 为 slave1 的 SlaveInotify.sh 添加 rsync 同步功能
$ cd linux
$ sudo gedit SlaveInotify.sh#!/bin/bash
# filename : SlaveInotify.sh
# author : dudu
# time : 2020/10/25
# work : Detect changes in flag.txt files and start synchronization with content 1
### Parameters
path=/home/mpi/linux
##### rsync实现文件同步功能
### Synchronization function
StartSy(){
flag=`cat KaTeX parse error: Can't use function '\`' in math mode at position 19: …h/flag/flag.txt\̲`̲<br> &nb…flag"
if [ KaTeX parse error: Expected 'EOF', got '&' at position 18: …ag == 1 ]<br> &̲nbsp; &nb…path/bigfile $path
echo “Synchronization success!!”
fi
}
### Listening Function
inotifywait -mrq --timefmt ‘%y/%m/%d %H:%M’ --format ‘%T %w %f’ -e modify,delete,create,attrib $path/flag | while read file
do
# Synchronization function
echo “Receiving synchronization information”
# StartSy
done5.6.2 将 监听脚本 添加开机自启服务中
# 对 master 执行
$ cd /etc/rc.d/init.d
$ chkconfig --add /home/mpi/linux/inotify.sh
$ chkconfig /home/mpi/linux/inotify.sh on
# 对 slave1 执行
$ cd /etc/rc.d/init.d
$ chkconfig --add /home/mpi/linux/SlaveInotify.sh
$ chkconfig /home/mpi/linux/SlaveInotify.sh on
# 重启master和slave1服务器
5.6.3 测试目录同步
# 在 master 的 bigfile 目录下修改大文件 bigfile.txt
![avatar][base64str18]
# 查看数据库 MD5 数据表变化
![avatar][base64str19]
# 查看 slave1 的同步是否成功
![avatar][base64str20]
注 : 主从同步目录成功
5.7 rsync实现双向文件同步
5.7.1 将 master 的linux文件夹 scp 到 slave 中,并将slave1的SlaveInotify.sh cp进去和传输到master中。同时将监听脚本 添加开机自启服务中*
$ scp -r mpi@slave1:/home/mpi/linux /home/mpi/linux
$ scp SlaveInotify.sh mpi@master:/home/mpi/linux
# 添加开机自启服务参考 5.6.2
注 : 每一台服务器都具有目录监听脚本 inotify.sh 和 flag.txt同步信息监听脚本 SlaveInotify.sh,但是这样的话就会出现互相覆盖修改,导致目录同步进入死循环。为了解决这个问题在创建一个监听判断文件Judgment.txt5.7.2 使用监听判断文件Judgment.txt解决同步目录互相覆盖修改的问题
原理: 创建一个监听判断文件 Judgment.txt。inotify.sh监听文件内容为 0 时,判断为用户修改目录;监听文件内容为 1 时,判断同步操作修改目录。每发送一个同步信息flag信息的时候修改对方的 Judgment.txt 为 1 对伐执行完同步操作后 Judgment.txt 为 0
# 流程图
![avatar][base64str21]
# 修改work3.sh 脚本 在最后加上rm -rf $flagPath/Judgment.txt
echo “1” >> f l a g P a t h / J u d g m e n t . t x t < b r > s s h p a s s − p ′ 1 ′ s s h − t m p i @ s l a v e 1 " r m " flagPath/Judgment.txt<br> sshpass -p '1' ssh -t mpi@slave1 "rm " flagPath/Judgment.txt<br>sshpass−p′1′ssh−tmpi@slave1"rm"flagPath/flag/Judgment.txt “exit”
sshpass -p ‘1’ scp Judgment.txt mpi@slave1:$flagPath/flag# 修改 inotify.sh 脚本
![avatar][base64str22]5.7.3 测试双向文件同步
# master 创建文件c.txt
$ touch c.txt
![avatar][base64str23]
$ slave1 查看结果
![avatar][base64str24]
# slave1 创建文件d.txt
$ touch c.txt
![avatar][base64str25]
$ master 查看结果
![avatar][base64str26]
注 : 双向文件同步成功
6. 实验总结
- 该实验通过Inotify的监听、在判断MD5值的变化情况,最后通过rsync技术同步文件。
- 在实验终于到了许多问题scp如何自动输入密码传输文件、shell脚本如何实验函数调用和参数传递、两台电脑之间如何进行同步信息的传递和如何解决双向同步的互相覆盖修改问题。
- 该实验仍有许多需要改进的地方如:当文件非常大的时候,计算文件的MD5值是非常慢的,是否可以将文件分块在利用多线程的方法提高计算速度。
原文链接: https://gitee.com/linux-cwl/work-one/tree/master/Work3