首先分别介绍inotify 与 rsync的使用,然后用两者实现实时文件同步,最后说一下这样的系统存在什么样的问题。

1. inotify

这个具体使用网上很多,参考

inotify-tools 命令使用讲解

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

参考 Linux 下 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文件同步实现与问题的更多相关文章

  1. Rsync文件同步

    Rsync文件同步 本章结构 关于rsync 1.一款增量备份工具,remote sync,远程同步,支持本地复制或者与其他SSH.rsync主机同步,官方网站:http://rsync.samba. ...

  2. rsync文件同步、Inotify-tools参数详解

    inotifywait用于等待文件或文件集上的一个待定事件,可以监控任何文件和目录设置,并且可以递归地监控整个目录树: inotifywatch用于收集被监控的文件系统计数据,包括每个inotify事 ...

  3. CentOS系统rsync文件同步 安装配置

    rsync是类unix系统下的数据镜像备份工具,从软件的命名上就可以看出来了——remote sync 它的特性如下: 可以镜像保存整个目录树和文件系统. 可以很容易做到保持原来文件的权限.时间.软硬 ...

  4. rsync 文件同步和备份

    rsync 是同步文件的利器,一般用于多个机器之间的文件同步与备份,同时也支持在本地的不同目录之间互相同步文件.在这种场景下,rsync 远比 cp 命令和 ftp 命令更加合适,它只会同步需要更新的 ...

  5. Rsync文件同步工具

    前段时间因公司需求,需要把备份的文件进行同步保存,后面就想到了我们大家都最熟悉的文件同步工作Rsync,于是就捣鼓了一下午时间,然后总结了下大概过程和参数详情. 首先了解了下rsync同步的大致原理: ...

  6. linux 下的 rsync 文件同步

    rsync是linux下的一款快速增量备份工具Remote Sync,是一款实现远程同步功能的软件,它在同步文件的同时,可以保持原来文件的权限.时间.软硬链接等附加信息.rsync是用 “rsync ...

  7. Rsync文件同步服务器配置

    rsync 是一个Unix/Linux系统下的文件同步和传输工具.rsync是用 “rsync 算法”提供了一个客户机和远程文件服务器的文件同步的快速方法.可以用来做备份或镜像.一.配置文件rsync ...

  8. centos7下rsync+inotify脚本实现文件同步,.NET CORE客户端文件更新后自动重启服务

    源服务器IP:192.168.8.51 目标服务器IP:192.168.8.79 安装前源服务器及目标服务器均需关闭FIREWALLD\SELINUX防火墙 sestatus | grep statu ...

  9. [rsync]——rsync文件同步和备份

    实验环境 (1) Rsync服务器:10.0.10.158 (2) Rsync客户端:10.0.10.173 Rsync服务器端的配置 1. 安装xinetd和rsync # yum install ...

随机推荐

  1. python---web微信开发

    一:轮询,长轮询,WebSocket了解 轮询: 在前端,设置时间内,一直向后端发送请求.例如:使用setInterval方法设置定时器,一秒向后端发送一次请求,去主动获取数据,进行更新由于前端一直请 ...

  2. element ui 栅格布局

    <el-row> <el-col :span="24"><div class="grid-content bg-purple-dark&qu ...

  3. MySQL报错】ERROR 1558 (HY000): Column count of mysql.user is wrong. Expected 43, found 39.

    之前在centos6.4系统安装的是自带的mysql 5.1版本,后来升级到了5.6版本,执行以下命令报错 在网上查找原因说说因为升级不当导致,执行以下命令即可正常执行命令 mysql_upgrade ...

  4. HDU 5985 概率

    n种硬币各有cnt[i]枚,每轮下其有p[i]概率保留,问各种硬币只有它存活到最后一轮的概率. 设k轮后i硬币存活概率$a[i][k]=(1-p^k_i)^{cnt[i]}$ 则最后只有第i种硬币存活 ...

  5. UNDERSTANDING THE GAUSSIAN DISTRIBUTION

    UNDERSTANDING THE GAUSSIAN DISTRIBUTION Randomness is so present in our reality that we are used to ...

  6. markdown里的多层次列表项

    markdown里的多层次列表项 编写python的docstrng太多, 有时候就搞混淆了层次化列表项在博客或者随笔里的规则. docstirng里, 仅用两个空格的缩进就可以实现. 博客里通常是一 ...

  7. 【学习DIV+CSS】1. 你必须知道的三个知识

    1. DIV+CSS的叫法不够严谨 我们以前做页面布局的时候大多是用Table,很多人称之为“Table+CSS”,而现在比较流行的是DIV布局,所以称之为“DIV+CSS”.听起来是挺合理的,岂不知 ...

  8. 回调函数之基本的Promise

    在 JavaScript 中,所有的代码都是单线程的,所谓的回调函数就是为了处理一些异步的操作.而多层的回调函数嵌套是一种比较古老的处理方式,这种代码的弊端显而易见,结构混乱.代码冗余,而 Promi ...

  9. iframe元素的学习(笔记)

    什么是iframe:iframe元素即内联框架,iframe是内联的并且承前启后,对于外围的页面,iframe是一个普通的元素,对于iframe里面的内容,又是一个五脏俱全的页面.重下面的写法可以看出 ...

  10. 树形dp(B - Computer HDU - 2196 )

    题目链接:https://cn.vjudge.net/contest/277955#problem/B 题目大意:首先输入n代表有n个电脑,然后再输入n-1行,每一行输入两个数,t1,t2.代表第(i ...