inotify 与 rsync文件同步实现与问题
首先分别介绍inotify 与 rsync的使用,然后用两者实现实时文件同步,最后说一下这样的系统存在什么样的问题。
1. inotify
这个具体使用网上很多,参考
Inotify 内核版本支持
- 从 kernel 2.6.13 开始, Inotify 正式并入内核,RHEL5 已经支持.
- 看看是否有 /proc/sys/fs/inotify / 目录,以确定内核是否支持
- [root@RHEL5 Rsync]# ls -l /proc/sys/fs/inotify/
- total
- -rw-r--r-- root root Oct : max_queued_events
- -rw-r--r-- root root Oct : max_user_instances
- -rw-r--r-- root root Oct : max_user_watches
/proc/sys/fs/inotify/max_queued_events 默认值: 16384 该文件中的值为调用 inotify_init 时分配给 inotify instance 中可排队的 event 的数目的最大值,超出这个值得事件被丢弃,但会触发 IN_Q_OVERFLOW 事件
/proc/sys/fs/inotify/max_user_instances 默认值: 128 指定了每一个 real user ID 可创建的 inotify instatnces 的数量上限
/proc/sys/fs/inotify/max_user_watches 默认值: 8192 指定了每个 inotify instance 相关联的 watches 的上限
注意: max_queued_events 是 Inotify 管理的队列的最大长度,文件系统变化越频繁,这个值就应该越大
如果你在日志中看到 Event Queue Overflow,说明 max_queued_events 太小需要调整参数后再次使用.
实例:
- inotifywait -mrq --timefmt '%y%m%d %H:%M' --format '%T %e %w%f' -o log.txt -e modify,create,delete /data
参数说明
语法:
inotifywait [-hcmrq] [-e ] [-t ] [--format ] [--timefmt ] [ ... ]
参数:
-h,–help
输出帮助信息
@
排除不需要监视的文件,可以是相对路径,也可以是绝对路径。
–fromfile
从文件读取需要监视的文件或排除的文件,一个文件一行,排除的文件以 @开头。
-m, –monitor
接收到一个事情而不退出,无限期地执行。默认的行为是接收到一个事情后立即退出。
-d, –daemon
跟–monitor 一样,除了是在后台运行,需要指定–outfile 把事情输出到一个文件。也意味着使用了–syslog。
-o, –outfile
输出事情到一个文件而不是标准输出。
-s, –syslog
输出错误信息到系统日志
-r, –recursive
监视一个目录下的所有子目录。
-q, –quiet
指定一次,不会输出详细信息,指定二次,除了致命错误,不会输出任何信息。
–exclude
正则匹配需要排除的文件,大小写敏感。
–excludei
正则匹配需要排除的文件,忽略大小写。
-t , –timeout
设置超时时间,如果为 0,则无限期地执行下去。
-e , –event
指定监视的事件。
-c, –csv
输出 csv 格式。
–timefmt
指定时间格式,用于–format 选项中的 %T 格式。
–format
指定输出格式。
%w 表示发生事件的目录
%f 表示发生事件的文件
%e 表示发生的事件
%Xe 事件以 “X” 分隔
%T 使用由–timefmt 定义的时间格式
可监听事件
access | 文件读取 |
modify | 文件更改。 |
attrib | 文件属性更改,如权限,时间戳等。 |
close_write | 以可写模式打开的文件被关闭,不代表此文件一定已经写入数据。 |
close_nowrite | 以只读模式打开的文件被关闭。 |
close | 文件被关闭,不管它是如何打开的。 |
open | 文件打开。 |
moved_to | 一个文件或目录移动到监听的目录,即使是在同一目录内移动,此事件也触发。 |
moved_from | 一个文件或目录移出监听的目录,即使是在同一目录内移动,此事件也触发。 |
move | 包括 moved_to 和 moved_from |
move_self | 文件或目录被移除,之后不再监听此文件或目录。 |
create | 文件或目录创建 |
delete | 文件或目录删除 |
delete_self | 文件或目录移除,之后不再监听此文件或目录 |
unmount | 文件系统取消挂载,之后不再监听此文件系统。 |
2.rsync
实例
- rsync -azcvR /data /backup
具体各参数的含义参考链接文件
3.inotify+rsync 同步
参考 真正的 inotify+rsync 实时同步 彻底告别同步慢
代码
- #!/bin/bash
- /usr/bin/inotifywait -mrq --format '%w%f'-e create,close_write,delete /backup |while read file
- #把发生更改的文件列表都接收到 file 然后循环, 下面做的是全量 rsync
- do
- cd /backup && rsync -az --delete /backup/ rsync_backup@192.168.24.101::backup/--password-file=/etc/rsync.password
- done
这个程序有个问题,就是每当inotify检测到有事件发生,都进行同步一次,太麻烦
优化:
- #!/bin/bash
- src=/home/dahu/Homework/daqing # 需要同步的源路径
- des=/home/dahu/Homework/daqing.bk # 目标服务器上
- cd ${src} # 此方法中,由于 rsync 同步的特性,这里必须要先 cd 到源目录,inotify 再监听 ./ 才能 rsync 同步后目录结构一致,有兴趣的同学可以进行各种尝试观看其效果
- function myfunc { #检测父文件夹是否存在
- if [ -d $(dirname $) ]
- then
- echo "$(dirname $1)"
- else
- dir=`dirname $`
- myfunc $dir
- fi
- }
- true && {
- inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move ./ | while read file # 把监控到有发生更改的 "文件路径列表" 循环
- do
- INO_EVENT=$(echo $file | awk '{print $1}') # 获取事件
- INO_FILE=$(echo $file | awk '{print $2}') # 获取文件
- echo "-------------------------------$(date)------------------------------------"
- echo $file
- #增加、写入完成、移动进事件
- if [[ $INO_EVENT =~ 'CREATE' ]] || [[ $INO_EVENT =~ 'CLOSE_WRITE' ]] || [[ $INO_EVENT =~ 'MOVED_TO' ]]
- then
- echo 'CREATE or CLOSE_WRITE or MOVED_TO'
- rsync -avzcuR $(dirname ${INO_FILE}) ${des}
- #仅仅更新新的东西,需要加个u,也就是跳过所有已经存在于 DST,并且文件时间晚于要备份的文件。(不覆盖更新的文件)
- fi
- #修改事件
- if [[ $INO_EVENT =~ 'MODIFY' ]]
- then
- echo 'MODIFY'
- rsync -avzcR ${INO_FILE} ${des}
- #修改文件,只需要同步该文件即可
- fi
- #删除、移动出事件
- if [[ $INO_EVENT =~ 'DELETE' ]] || [[ $INO_EVENT =~ 'MOVED_FROM' ]]
- then
- echo 'DELETE or MOVED_FROM'
- rsync -avzuR --delete $(myfunc ${INO_FILE}) ${des}
- #看 rsync 命令 如果直接同步已删除的路径 ${INO_FILE} 会报 no such or directory 错误 所以这里同步的源是被删文件或目录的上一级路径,并加上 --delete 来删除目标上有而源中没有的文件,这里不能做到指定文件删除,如果删除的路径越靠近根,则同步的目录月多,同步删除的操作就越花时间。这里有更好方法的同学,欢迎交流。
- fi
- #修改属性事件 指 touch chgrp chmod chown 等操作
- if [[ $INO_EVENT =~ 'ATTRIB' ]]
- then
- echo 'ATTRIB'
- if [ ! -d "$INO_FILE" ] # 如果修改属性的是目录 则不同步,因为同步目录会发生递归扫描,等此目录下的文件发生同步时,rsync 会顺带更新此目录。
- then
- rsync -avzcuR ${INO_FILE} ${des}
- fi
- fi
- done
- }
优化思路就是,把每次不同类型的事件,做一个分解:
修改文件的,只同步该文件即可;
增加文件或文件夹的,更新文件夹目录,注意这里的更新,是指 rsync -u 仅仅进行更新,也就是跳过所有已经存在于 DST,并且文件时间晚于要备份的文件。(不覆盖更新的文件),如果你修改了原文件的内容,但不改变名字,就意味着不同步到DST,所以先把修改内容的情况考虑了
删除文件时,这个时候你再同步,即使使用rsync --delete, 删除那些 DST 中 SRC 没有的文件,但是这个文件夹已经删除了,所以得需要访问他存在的父文件夹,不然会报错
即使这3个优化过了,但还是会慢,为什么?
遇到大文件的情况,或者是简单的用vim 生成文件,这个时候inotify 会监控到很多中间文件(如vim的swp),大文件的各种modify操作,都会监控到,这个时候再用刚刚那个程序,每次监控到一个事件,(即使是优化过了,只值针对该文件,不优化的话要同步所有的),都要同步一次,麻烦且耗时。
假设你生成1G的文件,会监控到100次的modify事件,即同步100次,那就是rsync 100*1G,当然使用-u这个参数会好一点,但是如果是修改大文件又保存呢?想象一下就知道需要不停的同步,况且,必须得等到这些前面的循环都跑完了再跑后面的,这个同步的时间不能做到很及时。 刚刚又实验了一下,7.4M的文件,需要419次
4.自己改进
优化的思路来源于第三点的疑问,我没必要同步那么多次(代码中的-u),在这里我在单位时间(2s)内,先把所有操作去重(针对大文件),把modify和别的操作区分对待,对modify的操作同步对应文件,其余的更新父文件夹,记得加-u 和--delete即可。应该算是解决了第3点提出的疑问,重复次数不会很多,暂时测试效果还可以。
- cat tt.sh
- #!/bin/bash
- src=/home/dahu/Homework/daqing # 需要同步的源路径
- des=/home/dahu/Homework/daqing.bk # 目标服务器
- cd `dirname $src`
- rm -rf log*
- inotifywait -mrq --format '%Xe %w%f' -e modify,create,delete,attrib,close_write,move `basename $src` > log &
- function testdir { #显示存在的最深的文件夹
- #echo 'hehe'
- if [ -d $(dirname $) ]
- then
- echo "$(dirname $1)"
- else
- dir=`dirname $`
- testdir $dir
- fi
- }
- #myfunc daqing/p/q/r/s/t
- #2s一次循环
- cyclenum=`wc -l log |awk '{print $1+1}'`
- while true
- do
- lastnum=$cyclenum
- sleep
- sec=`date +%S`
- if [ `expr $sec % ` = "" ]
- then
- #date
- #这种方法是失效的,why,因为> ,文件删除或者move,就不会再继续往里添加文件了,所以按指定行数来显示比较靠谱
- #cat log > log.
- #md1=`md5sum log|awk '{print $1}'` && md2=`md5sum log.|awk '{print $1}'`
- #if [ $md1 != $md2 ] ;then echo "md5 not equal" && continue ;fi
- #touch log. && mv log. log && cat log. >> log.all
- cyclenum=`wc -l log |awk '{print $1+1}'`
- #sed -n '94,2p'
- sed -n "${lastnum},${cyclenum}p" log > log. #这一轮的操作, 暂时证明这个方法是可用的
- #sed -n "${lastnum},${cyclenum}p" log >> log.all #用来检测是否漏掉监控的操作
- sort -u log. > log.uniq
- for line in `grep "MODIFY" log.uniq|awk '{print $2}'`
- do
- #echo $line
- if [ -f $line ] ;then rsync -avzcR $line $des;fi
- done
- for line in `awk '{print $2}' log.uniq`
- do
- dir=`testdir $line`
- rsync -avzuR --delete $dir $des
- done
- fi
- done
inotify 与 rsync文件同步实现与问题的更多相关文章
- Rsync文件同步
Rsync文件同步 本章结构 关于rsync 1.一款增量备份工具,remote sync,远程同步,支持本地复制或者与其他SSH.rsync主机同步,官方网站:http://rsync.samba. ...
- rsync文件同步、Inotify-tools参数详解
inotifywait用于等待文件或文件集上的一个待定事件,可以监控任何文件和目录设置,并且可以递归地监控整个目录树: inotifywatch用于收集被监控的文件系统计数据,包括每个inotify事 ...
- CentOS系统rsync文件同步 安装配置
rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync 它的特性如下: 可以镜像保存整个目录树和文件系统. 可以很容易做到保持原来文件的权限.时间.软硬 ...
- rsync 文件同步和备份
rsync 是同步文件的利器,一般用于多个机器之间的文件同步与备份,同时也支持在本地的不同目录之间互相同步文件.在这种场景下,rsync 远比 cp 命令和 ftp 命令更加合适,它只会同步需要更新的 ...
- Rsync文件同步工具
前段时间因公司需求,需要把备份的文件进行同步保存,后面就想到了我们大家都最熟悉的文件同步工作Rsync,于是就捣鼓了一下午时间,然后总结了下大概过程和参数详情. 首先了解了下rsync同步的大致原理: ...
- linux 下的 rsync 文件同步
rsync是linux下的一款快速增量备份工具Remote Sync,是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限.时间.软硬链接等附加信息.rsync是用 “rsync ...
- Rsync文件同步服务器配置
rsync 是一个Unix/Linux系统下的文件同步和传输工具.rsync是用 “rsync 算法”提供了一个客户机和远程文件服务器的文件同步的快速方法.可以用来做备份或镜像.一.配置文件rsync ...
- centos7下rsync+inotify脚本实现文件同步,.NET CORE客户端文件更新后自动重启服务
源服务器IP:192.168.8.51 目标服务器IP:192.168.8.79 安装前源服务器及目标服务器均需关闭FIREWALLD\SELINUX防火墙 sestatus | grep statu ...
- [rsync]——rsync文件同步和备份
实验环境 (1) Rsync服务器:10.0.10.158 (2) Rsync客户端:10.0.10.173 Rsync服务器端的配置 1. 安装xinetd和rsync # yum install ...
随机推荐
- Django paginator and Form
django 提供的分页器 django 官方链接: https://docs.djangoproject.com/en/1.11/topics/pagination/ django提供了一些类来帮 ...
- 「Vue」vue cli3中axios的基本用法
1.安装axiosnpm i axios -S2.main.js中设置import axios from 'axios'Vue.prototype.$axios = axiosPS:这里有个小坑,ax ...
- OpenStack安装部署(二)
中文文档:http://docs.openstack.org/mitaka/zh_CN/install-guide-rdo/提示:这个中文文档是直接翻译过来的,所以会有很多不通顺的地方. 服务介绍 M ...
- python——type()、metaclass元类和精简ORM框架
1.type()函数 if __name__ == '__main__': h = hello() h.hello() print(type(hello)) print(type(h)) Hello, ...
- java基础-引用数据类型之二维数组(Array)
java基础-引用数据类型之二维数组(Array) 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 之前我们学习过了Java的一维数组,所谓的二维数组就是元素是一堆一维数组的数组,换 ...
- 科学计算三维可视化---Mlab基础(改变物体的外观颜色)
import numpy as np from mayavi import mlab #建立数据 x,y = np.mgrid[-::200j,-::200j] z = *np.sin(x*y)/(x ...
- 博世传感器调试笔记(一)----加速度传感器BMA253
公司是bosch的代理商,最近一段时间一直在公司开发的传感器demo板上调试bosch sensor器件.涉及到的器件有7,8款,类型包括重力加速度.地磁.陀螺仪.温度.湿度.大气压力传感器等.在调试 ...
- JavaScript setInterval 与 setTimeout 区别
setInterval:一直循环调用函数,不会停止:需要用 clearInterval 去停止 setTimeout:只调用一次
- 【学习DIV+CSS】2. 学习CSS(一)--CSS控制页面样式
1. CSS如何控制页面 使用XHTML+CSS布局页面,其中有一个很重要的特点就是“结构与表现相分离”(结构指XHTML,表现指CSS).有人这样描述这种分离的关系,结构XHTML好比一个人,表现C ...
- [整理]C中的静态存储区
静态存储区:即内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在.它主要存放静态数据.全局数据和常量.栈区:在执行函数时,函数内局部变量的存储单元都可以在栈上创建,函数执行结束时这些 ...