rsync的优点与不足
上篇文章我们介绍了如何使用rsync同步文件,这篇文章我们再来介绍下,如何把rsync与inotify集成实现数据的实时同步。
rsync在Linux/Unix下是一个比较重要和实用的服务,大家应该已经知道rsync具有安全性高、备份迅速、支持增量备份等优点。通过rsync可以解决对实时性要求不高的数据备份需求,例如:定期备份文件服务器数据到远端服务器,对本地磁盘定期做数据镜像等。随着应用系统规模的不断扩大,对数据安全性和可靠性也提出了更高的要求,rsync在高端业务系统中也逐渐暴露出它的不足。
首先,rsync在进行同步数据时,需要先扫描所有文件后进行比对,然后再进行差量传输。如果文件数量达到百万甚至千万级,扫描所以文件将是非常耗时的。而且发生变化的往往是其中很少的一部分文件,这是非常低效的方式。其次,rsync不能实时地去监测、同步数据。虽然它可以通过Linux守护进程的方式触发同步,但是两次触发动作之间一定会有时间差。这样就可能会导致服务端和客户端数据出现不一致的情况,无法在应用出现故障时完全恢复数据。
基于以上原因,所以就考虑采用rsync与inotify集成的方式来解决这些问题。
inotify是什么?
inotify是一种强大的、细粒度的、异步的文件系统事件监控机制。Linux内核从2.6.13(2005年8月)起,加入了对inotify的支持,通过inotify可以监控文件系统中的添加、删除、修改、移动等各种细微事件。利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools就是这样一个第三方软件。
在上面章节中,我们讲到,rsync可以实现触发式的文件同步。它是通过crontab守护进程方式触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变化时,就触发rsync同步,这就刚好解决了数据同步实时性的问题。
检测OS是否支持inotify
由于inotify特性需要Linux内核的支持,所以在安装inotify-tools之前要先确认Linux系统内核是否达到2.6.13以上。如果Linux内核低于2.6.23版本,就需要重新编译内核加入对inotify的支持,也可以用如下的方法来判断Linux内核是否支持inotify。
1 2 3 4 5 6 7 8 |
[root@www ~]# uname -r 2.6.32-431.23.3.el6.x86_64 [root@www ~]# yum stall inotify-tools [root@www ~]# ll /proc/sys/fs/inotify/ total 0 -rw-r--r-- 1 root root 0 Apr 15 18:47 max_queued_events -rw-r--r-- 1 root root 0 Apr 15 18:47 max_user_instances -rw-r--r-- 1 root root 0 Apr 15 18:47 max_user_watches |
inotify定义了三个接口参数,可以用来限制inotify消耗kernel memory的大小。由于这些参数都是内存参数,因此,可以根据应用需求实时的调节其大小。下面分别做简单介绍:
max_queued_evnets – 表示请求events数的最大值,超出这个值的事件将被丢弃。该值默认为16384。
注意:max_queued_events是inotify管理的队列的最大长度,文件系统变化越频繁,这个值就应该越大。
如果你在日志中看到Event Queue Overflow,说明max_queued_events太小需要调整参数后再次使用。
max_user_instances – 表示每个user可创建的instances数量上限。该值默认为128。
max_user_watches – 表示可监控目录的最大数。该值默认为8192。
要修改以上默认值,我们可以使用以下类似手段修改。如:echo 30000000 > /proc/sys/fs/inotify/max_user_watches
inotify监控的文件事件类型
inotify可监控的文件系统事件类型,如下:
IN_ACCESS – 文件被访问。
IN_MODIFY – 文件被write。
IN_ATTRIB – 文件属性被修改,如chmod、chown等。
IN_CLOSE_WRITE – 可写文件被close。
IN_CLOSE_NOWRITE – 不可写文件被close。
IN_OPEN – 文件被open。
IN_MOVED_FROM – 文件被移出被监控目录,如mv。
IN_MOVED_TO – 文件被移入被监控目录,如mv、cp。
IN_CREATE – 文件/文件夹被创建。
IN_DELETE – 文件/文件夹被删除,如rm。
IN_DELETE_SELF – 自删除,即一个可执行文件在执行时删除自己。
IN_MOVE_SELF – 自移动,即一个可执行文件在执行时移动自己。
IN_UNMOUNT – 宿主文件系统被umount。
IN_CLOSE – 文件被关闭,等同于(IN_CLOSE_WRITE|IN_CLOSE_NOWRITE)。
IN_MOVE – 文件被移动,等同于(IN_MOVED_FROM|IN_MOVED_TO)。
注意:上面所说的文件也包括目录。
inotify-tools是什么?
inotify仅仅是一个API,需要通过开发应用程序进行调用。inotify-tools就是这样的一个inotify软件,它是一套组件,包括一个C库和几个命令行工具。这些命令行工具可用于通过命令行或脚本对某些文件系统的事件进行监控。
inotify是为替代dnotify而设计的,它克服了dnotify的缺陷,提供了更好用的,更简洁而强大的文件变化通知机制。
1) inotify不需要对被监视的目标打开文件描述符,而且如果被监视目标在可移动介质上,那么在umount该介质上的文件系统后,被监视目标对应的watch将被自动删除,并且会产生一个umount事件。
2) inotify既可以监视文件,又可以监视目录。
3) inotify使用系统调用而非SIGIO信号来通知文件系统事件。
4) inotify使用文件描述符作为接口,因而可以使用通常的文件I/O操作select和poll来监视文件系统的变化。
1 2 3 4 5 6 7 8 9 |
[root@localhost ~]# wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm [root@localhost ~]# rpm -ivh epel-release-6-8.noarch.rpm [root@localhost ~]# yum install inotify-tools [root@localhost ~]# rpm -ql inotify-tools /usr/bin/inotifywait /usr/bin/inotifywatch /usr/lib64/libinotifytools.so.0 /usr/lib64/libinotifytools.so.0.4.1 /usr/share/doc/inotify-tools-3.14 |
一、inotifywait命令详解
有关inotifywait的使用方法,我们可以通过它的帮助信息查看。如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
[root@localhost ~]# inotifywait -h [options] -m:表示始终保持事件监听状态。 -r:表示递归查询目录。 -q:表示打印出监控事件。 -e:通过此参数可以指定要监控的事件。 access:访问,读取文件。 modify:修改,文件内容被修改。 attrib:属性,文件元数据被修改。 move:移动,对文件进行移动操作。以及重命名,对文件进行重命名。 create:创建,生成新文件 open:打开,对文件进行打开操作。 close:关闭,对文件进行关闭操作。 delete:删除,文件被删除。 --timefmt:是指定时间的输出格式,用于–format选项中的%T格式。 --format:指定文件变化的详细信息输出格式,格式参数如下: %w表示发生事件的目录 %f表示发生事件的文件 %e表示发生的事件 %T使用由–timefmt定义的时间格式 %Xe事件以“X”分隔 |
inotifywait命令实例
inotifywait命令的参数,下面我们来实际使用下inotifywait命令。我们要监测/home目录下所有文件及目录的变化情况,命令如下:
1 |
[root@localhost ~]# inotifywait -mrq --timefmt '%y/%m/%d/%H:%M' --format '%T %w %f %e' -e modify,delete,create,attrib,move,open,close,access /home/ |
这条命令表示对/home目录下所有文件及目录的操作进行监控。现在我们打开另外一个窗口对/home目录进行操作,如下:
1 2 |
[root@localhost ~]# cd /home/ [root@localhost home]# mkdir file |
我们是在/home目录下创建一个新的目录file。现在我们来切换到刚刚执行inotifywait命令的窗口,如下:
1 2 3 4 5 6 7 8 |
[root@localhost ~]# inotifywait -mrq --timefmt '%y/%m/%d/%H:%M' --format '%T %w %f %e' -e modify,delete,create,attrib,move,open,close,access /home/ 16/04/15/19:41 /home/ OPEN,ISDIR 16/04/15/19:41 /home/ CLOSE_NOWRITE,CLOSE,ISDIR 16/04/15/19:41 /home/ OPEN,ISDIR 16/04/15/19:41 /home/ CLOSE_NOWRITE,CLOSE,ISDIR 16/04/15/19:41 /home/ file CREATE,ISDIR 16/04/15/19:41 /home/ file OPEN,ISDIR 16/04/15/19:41 /home/ file CLOSE_NOWRITE,CLOSE,ISDIR |
二、inotifywatch命令详解
除了inotifywatit命令之外,inotify-tools还有一个命令inotifywatch。inotifywatch主要用于收集被监控的文件系统统计数据,包括每个inotify事件发生多少次等信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
[root@localhost ~]# inotifywatch -h [options] -h:输出帮助信息。 -v:输出详细信息。 @:排除不需要监视的文件,可以是相对路径,也可以是绝对路径。 –-fromfile:从文件读取需要监视的文件或排除的文件,一个文件一行,排除的文件以@开头。 -z:输出表格的行和列,即使元素为空。 –-exclude:正则匹配需要排除的文件,大小写敏感。 –-excludei:正则匹配需要排除的文件,忽略大小写。 -r:监视一个目录下的所有子目录。 -t:设置超时时间。 -e:只监听指定的事件,该事件与inotifywait监听的事件类型一样。 -a:以指定事件升序排列。 -d:以指定事件降序排列。 |
inotifywatch命令实例
我们讲解了inotifywatch命令的参数,下面我们来实际使用下inotifywatch命令。要求统计60秒内/home目录下文件系统的事件,使用如下命令:
Shell 1(使用inotifywatch)
1 |
[root@localhost ~]# inotifywatch -v -e modify,delete,create,attrib,move,open,close,access -e modify -t 60 -r /home |
Shell 2(创建文件)
1 |
[root@localhost home]# touch newfile |
现在我们来切换到刚刚执行inotifywatch命令的窗口,如下:
1 2 3 4 5 6 7 8 9 |
[root@localhost ~]# inotifywatch -v -e modify,delete,create,attrib,move,open,close,access -e modify -t 60 -r /home Establishing watches... Setting up watch(es) on /home OK, /home is now being watched. Total of 2 watches. Finished establishing watches, now collecting statistics. Will listen for events for 60 seconds. total close_nowrite open moved_from moved_to filename 6 2 2 1 1 /home/ |
inotify-tools与rsync集成
inotify-tools与rsync的集成主要是通过inotifywait命令与rsync命令集成来实现的,并且该集成主要是体现的rsync客户端,而rsync服务器端正需要按照正常的配置进行即可。现在的要求是只要rsync客户端的/data目录下有任何文件或者目录有改动的情况,都要实时的同步到rsync服务器上。
注意:该集成的主要目的是把rsync客户端需要备份的文件实时推送到rsync服务器上。rsync如何配置看前面一篇关于rsync的文章,这里只贴出rsync服务器端的配置文件内容。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[root@locaohost ~]# vi /etc/rsyncd.conf uid=root gid=root max connections=4 log file=/var/log/rsyncd.log pid file=/var/run/rsyncd.pid lock file=/var/run/rsyncd.lock secrets file=/etc/rsyncd.passwd hosts deny=172.16.78.0/22 #拒绝某些IP访问服务器,默认拒绝所有,所以这里我随意写了一个IP段 #hosts allow=172.16.78.0/22 #只允许某些IP访问服务器,也可以定义在每个标签中 [data] comment= backup web path=/data read only = no exclude=test auth users=work |
接下来,我们的所有操作都是在rsync客户端上进行的,其实inotifywait命令与rsync命令集成,我们所要做的只是写一个shell脚本即可。脚本内容如下:
1 2 3 4 5 6 7 8 9 10 |
[root@localhost ~]# cat /tmp/rsync.sh #!/bin/bash src=/data dest=data inotifywait -mrq --timefmt '%d/%m/%y%H:%M' --format '%T %w %f' -e modify,delete,create,attrib $src | while read DATETIME DIR FILE; do changefile=${DIR}${FILE} rsync -avz --delete --progress $src work@112.74.99.130::$data --password-file=/etc/rsyncd.password & echo "At ${DATETIME}, file $changefile was backed up via rsynce" >> /tmp/rsync.log 2>&1 done |
该脚本的原理是利用inotifywait命令对指定的文件和目录进行监控,如果指定文件和目录有改变那么就启动rsync同步命令。
把用户密码写入到–password-file指定的配置文件中。
1 |
[root@localhost ~]# echo "work:abc123" > /etc/rsyncd.password |
开始启动脚本了。
1 |
[root@localhost ~]# sh /tmp/rsync.sh |
然后客户端打开另一个窗口,开始创建一个文件试试看有没有同步到远程服务器上面去。
1 |
[root@localhost ~]# touch /data/one |
看一下日志,说/data/one文件同步成功。
1 2 |
[root@localhost ~]# cat /tmp/rsync.log At 26/04/1513:30, file /data/one was backed up via rsynce |
更多用法自己研究研究。