附录B rsync及inotify在工作中的应用

大家应该很熟悉和了解Linux下的rsync工具了吧,rsync(remote synchronize)是一个远程数据同步工具,可通过LAN/WAN快速同步多台主机间的文件。rsync使用rsync算法来使本地主机和远程主机之间的文件达到同步,这个算法并不是每次都整份传送,它只传送两个文件的不同部分,因此速度相当快。

rsync的优点如下:

广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元

·可以镜像保存整个目录树和文件系统。

·可以很容易做到保持原来文件的权限、时间、软硬链接等。

·无需特殊权限即可安装。

·拥有优化的流程,文件传输效率高。

·可以使用RSH、SSH等方式来传输文件,当然也可以直接通过Socket连接。

·支持匿名传输。

另外,与scp相比,它们的传输速度不是一个数量级的。我们在局域网时经常用rsync和scp传输大量数据文件,发现rsync在速度上至少比scp快20倍以上,这得益于rsync强大的checksum算法。所以大家如果需要在Linux服务器之间传输大数据时,rsync是最好的选择。rsync 2.6.8版本中存在Bug,不过在2.6.9版本中已解决。另外,rsync3.0版本的算法相对于rsync2.x的算法也有所改善,3.0是边对比边同步,2.x是完全对比之后再同步,3.0的效率肯定更高,所以这里推荐大家采用3.0或更高级的版本。CentOS 6.4 x86_64下我们可以用如下命令来查看rsync的版本号,如下所示:

rsync --version

命令显示结果如下所示:

rsync version 3.0.6 protocol version 30

Copyright (C) 1996-2009 by Andrew Tridgell, Wayne Davison, and others.

Web site: http://rsync.samba.org/

Capabilities:

64-bit files, 64-bit inums, 64-bit timestamps, 64-bit long ints,

socketpairs, hardlinks, symlinks, IPv6, batchfiles, inplace,

append, ACLs, xattrs, iconv, symtimes

rsync comes with ABSOLUTELY NO WARRANTY. This is free software, and you

are welcome to redistribute it under certain conditions. See the GNU

General Public Licence for details.

关心rsync算法的朋友可以关注下面的文章,如下所示:

http://coolshell.cn/articles/7425.html

http://en.wikipedia.org/wiki/Rolling_hash

http://en.wikipedia.org/wiki/Adler-32

http://wangyuanzju.blog.163.com/blog/static/130292010101252632998/

http://blog.csdn.net/liuben/article/details/5793706

http://blog.csdn.net/liuben/article/details/5693974

如果遇到网页打不开的情况,推荐大家使用shadowsocks翻墙,下载地址为:https://github.com/shadowsocks/shadowsocks-windows 。

B.1 rsync的应用模式

笔者建议将安装及提供rsync服务的机器称为rsync服务器端,没有提供rsync的机器称为rsync客户端,这样可以更好地理解本节的内容。这里笔者按照rsync平时在工作中的应用,将其分成了4种应用模式,如下所示:

1)本地Shell模式,顾名思义,此操作主要是针对本地机器的,用于在本地机器上复制目录内容。

2)远程Shell模式

使用一个远程Shell程序来实现将rsync服务器端的内容拷贝到本地机器,或者将本地机器的内容拷贝到rsync服务器端的机器中。

3)列表模式,可以通过rsync查看远程机器的目录信息。

如:rsync-v 192.168.1.204:/data/html/www/images/

4)服务器模式。

这个在工作中应该是应用得最多的,rsync服务器开启rsync服务,用于接收rsync客户端的文件传输请求。

那么,究竟应该如何在CentOS 6.4下实现rsync服务呢?这里以工作机器举例说明。

具体安装步骤如下:

首先准备一台系统为CentOS 6.4 x86_64、IP为192.168.1.207的机器,将其作为rsync服务器,另外准备一台系统为CentOS 6.4 x86_64、IP为192.168.1.204的机器作为rsync客户端。

具体的安装步骤不再多说,这里只介绍重点内容。首先检查rsync是否安装,命令如下:

rpm –

q rsync

命令显示结果如下:

rsync-3.0.6-12.el6.x86_64

如果没有安装rsync,大家可以使用如下命令进行安装:

yum –

y install rsync

另外,关闭防火墙和SELinux,因为是在内网中传输,所以没必要打开。关闭它们,免得引起不必要的麻烦,命令如下:

service iptables stop

chkconfig iptables off

setenforce 0

下面分享一下我自己定义的配置文件/etc/rsyncd.conf(说明:此文件并不是系统创建的,大家也可以给它取不同的名字)。先给出具体代码,后面再进行详细解释,代码如下所示:

uid = www

gid = www

user chroot = no

max connections = 200

timeout = 600

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsyncd.lock

log file = /var/log/rsyncd.log

[www_rync]

path=/data/html/www/images/

ignore errors

read only = no

list = no

hosts allow = 192.168.21.0/255.255.255.0

auth users = test

secrets file = /etc/rsyncd.password

下面说明一下/etc/rsyncd.conf的语法。

uid = www

上面指的是运行rsync的用户为www。

gid = www

表示运行rsync的组为www。

因为我们的线上系统运行Nginx也是用的www:www用户,这里为了保证rsync以后文件及文件夹的权限一致,所以这里也选用了www:www用户。

use chroot = no

如果“use chroot”指定为true,那么rsync在传输文件以前首先chroot到path参数所指定的目录下。这样做可实现额外的安全防护功能,但缺点是需要给用户以root的权限,并且不能备份通过外部的符号连接所指向的目录文件。在默认情况下,chroot的值为true。但是这一般是没有必要的,笔者选择no或false。

list = no

表示不允许列清单。

max connections = 200

表示最大连接数。

timeout = 600

表示覆盖客户指定的IP超时时间,也就是说rsync服务器不会永远等待一个崩溃的客户端。

pidfile = /var/run/rsyncd.pid

指的是pid文件的存放位置。

lock file = /var/run/rsync.lock

指的是锁文件的存放位置。

log file = /var/log/rsyncd.log

指的是日志文件的存放位置。

[www_rync]

这是认证模块名,即跟samba软件的语法是一样,是对外公布的名字。

path = /data/html/www/images

这是参与同步的目录。

ignore errors

表示可以忽略一些无关的I/O错误。

read only = no

表示允许读和写。

list = no

表示不允许列清单。

hosts allow = 192.168.1.0/255.255.255.0

这里跟samba的语法是一样的,只允许192.168.1.0/24网段的机器进行同步,拒绝其他一切网段连接。

auth users = www

指的是认证的用户名,这里为了权限的一致性,建议也选择www。

secrets file = /etc/rsyncd.password

指的是密码文件的存放地址。

启动服务器端的rsync,可通过xinetd来控制,这里要对rsync进行修改,我们先编辑rsync相关的文件/etc/xinetd.d/rsync,如下所示:

service rsync

{

disable = yes

socket_type = stream

wait = no

user = root

server = /usr/bin/rsync

server_args = --daemon

log_on_failure += USERID

}

将disable=yes改为disable=no,然后重启xinetd即可,命令如下:

/etc/ini.d/xinetd restart

配置中应该注意的问题如下所示。

·[www_rsync]:认证模块名,这个认证模块名是服务器对外的名字,机器同步时只会认这个名字。

·path=/data/html/www/images/:参与同步的目录的权限。如果此目录的权限不够,rsync同步是成功不了的。这里建议用如下命令进行检查。

ls -ld /data/html/www/images/

确保www:www用户对此目录有读、写和执行权限,命令如下所示:

chonw –

R www:www /data/html/www/images/

·注意用户名和密码的问题。

echo "www:www" >/etc/rsyncd.password

说明:这里我设置的是用户名和密码一致。为了安全起见,设置他的权限为600,如下所示:

chmod 600 /etc/rsyncd.password

rsync客户端配置:

echo "www" > /etc/rsyncd.password

这里只需要密码,不需要用户,免得要同步时还要进行手动互动,为了安全,一样配置600的权限,命令如下所示:

chmod 600 /etc/rsyncd.password

下面首先来说说在工作中经常遇到的rsync问题。

故障一:服务器端的目录不存在或无权限,故障描述如下:

@ERROR: chroot failed

rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

解决方法:创建目录或修改目录权限。

故障二:服务器端该模块(tee)需要验证用户名和密码,但客户端没有提供正确的用户名和密码,认证失败,故障描述如下:

@ERROR: auth failed on module tee

rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

解决方法:提供正解的用户名和密码。

故障三:服务器上不存在指定的模块,故障描述如下:

@ERROR: Unknown module 'tee_nonexists'

rsync error: error starting client-server protocol (code 5) at main.c(1522) [receiver=3.0.3]

解决方法:提供正确的模块名。

接着我们可以进行测试工作了。

在rsync客户端的机器上执行如下命令:

rsync -vzrtopg --delete /data/html/www/images/

www@192.168.1.207::www_sync --password-file=/etc/rsyncd.password

这时候就可以看到正确的同步效果了,结果如下所示:

sending incremental file list

deleting key/xen-cms-private

deleting key/xen-cms

deleting key/id_rsa_yhc.pub

deleting key/

deleting 201601211010099/upload/1/201601/index.html

deleting 201601211010099/upload/1/201601/Thumbs.db

deleting 201601211010099/upload/1/201601/11163217052267j3.doc

deleting 201601211010099/upload/1/201601/11115238075060e0.png

deleting 201601211010099/upload/1/201601/0503525603970obn.docx

deleting 201601211010099/upload/1/201601/0503412101818iro.docx

deleting 201601211010099/upload/1/201601/

deleting 201601211010099/upload/1/201512/index.html

deleting 201601211010099/upload/1/201512/

deleting 201601211010099/upload/1/

deleting 201601211010099/upload/

deleting 201601211010099/notify/

deleting 201601211010099/

sent 108 bytes received 9 bytes 21.27 bytes/sec

total size is 0 speedup is 0.00

阅读 ‧ 电子书库

注意

在rsync客户端机器上,/data/html/www/images/和/data/html/www/images进行rsync传输的效果截然不同。如果是/data/html/www/images,则会将images目录复制到rsync服务器端的/data/html//www/images/目录下;如果是/data/html/www/images/,则不传输目录本身,只传输目录中的文件内容。请大家在工作中注意这点。

下面再说说工作中经常用到的rsync参数,如下所示。

·-v--verbose:详细模式输出。

·-r--recursive:对子目录以递归模式处理。

·-p--perms:保持文件权限。

·-o--owner:保持文件属主信息。

·-g--group:保持文件属组信息。

·-t--times:保持文件时间信息。

·--delete:表示客户端上的数据要与服务器端完全一致,我们还是以上面的例子来说明,请看下面的rsync同步命令:

rsync -vzrtopg --delete /data/html/www/images/

www@192.168.1.207::www_sync --password-file=/etc/rsyncd.password

我们在这里引入了--delete参数,则会使得rsync客户端机器的/data/html/www/images目录跟rsync服务器端的/data/html/www/images目录保持完全一致,如果客户端机器上存在着rsync服务器端不存在的文件或目录,则会删除。

·--delete-excluded:删除接收端那些被该选项指定排除的文件。

·-z--compress:对备份的文件在传输时进行压缩处理。

·--exclude=文件或文件夹名:指定不需要传输的文件或文件夹名。

·--include=文件或文件夹名:指定需要传输的文件或文件夹名。

·--exclude-from=FILE:排除FILE中指定模式的文件。

·--include-from=FILE:不排除FILE中指定模式匹配的文件。

另外,我们在工作中经常遇到的一个问题是,经常需要快速删除海量文件,这个应该如何来实现呢?

有时候需要快速清空包含几百万个小文件的文件夹,我们一般会采用rm-rf*的方式来处理,但现在的服务器一般都是机械硬盘,这样不仅速度慢,而且磁盘I/O的压力也非常大,机器负载很容易就上去了,其实这个时候我们可以用rsync来快速清理。

比如说我们要清理//data/html/www/mall/Runtime目录里的文件,应该如何操作呢?步骤比较简单,如下所示:

1)建立一个空的文件夹,命令如下所示:

mkdir /tmp/test

2)用rsync删除/data/www/html/mall/Runtime目录,命令如下所示:

rsync --delete-before -a -v --progress --stats /tmp/test/ /data/html/www/mall/Runtime

这样我们要删除的/data/www/html/mall/Runtime目录就会被清空了,删除的速度也会非常快。

选项说明分别如下。

·–delete-before:接收者在传输之前进行删除操作。

·–progress:在传输时显示传输过程。

·-a:归档模式,表示以递归的方式传输文件,并保持所有文件的属性。

·-v:详细输出模式。

·-stats:给出某些文件的传输状态。

B.2 rsync+inotify实现数据的实时同步更新

1.rsync的优点与不足

rsync在Linux下是一个比较重要和实用的服务,从前面的内容大家应该已经了解rsync具有安全性高、备份迅速、支持增量备份等的优点,通过rsync可以解决对实时性要求不高的数据备份需求,例如定期地备份文件服务器数据到远程服务器,对本地磁盘定期做数据镜像等。

随着应用系统规模的不断扩大,对数据的安全性和可靠性也提出了更高的要求,rsync在高端业务系统中也逐渐暴露出了很多的不足之处,首先,rsync同步数据时,需要扫描所有文件后进行比对,然后进行差量传输。如果文件数量达到了百万甚至千万量级,那么扫描所有文件将是非常耗时的。而且正在发生变化的往往只是其中很少的一部分,这是非常低效的方式。其次,rsync不能实时地去监测、同步数据,虽然它可以通过Linux守护进程的方式触发同步,但是两次触发动作一定会有时间差,这样就导致了服务端和客户端数据可能出现不一致的情况,无法在应用故障时完全恢复数据。基于以上原因,考虑采用rsync+inotify,就可以解决这些问题了。

2.初识inotify

inotify是一种强大的、细粒度的、异步的文件系统事件监控机制,Linux内核从2.6.13起,加入了对inotify的支持,通过inotify可以监控文件系统中的添加、删除、修改、移动等各种细微事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况了,而inotify-tools就是这样一个第三方软件。

在上面的章节中我们讲到,rsync可以实现触发式的文件同步,但是通过Crontab守护进程的方式触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rsync同步,这就刚好解决了同步数据的实时性问题。

3.安装inotify工具inotify-tools

由于inotify的特性需要Linux内核的支持,在安装inotify-tools前先要确认Linux系统内核是否达到了2.6.13以上,如果Linux内核低于2.6.13版本,就需要重新编译内核加入对inotify的支持,我们的CentOS 6.4系统不需要担心此问题。

uname -r

命令显示结果如下所示:

2.6.32-573.12.1.el6.x86_64

然后我们通过ls来查看是否存在/proc/sys/fs/inotify目录,如下所示:

ls -lsart /proc/sys/fs/inotify/

此命令显示结果如下所示:

total 0

0 dr-xr-xr-x 0 root root 0 Feb 25 02:15 ..

0 dr-xr-xr-x 0 root root 0 Mar 2 03:36 .

0 -rw-r--r-- 1 root root 0 Mar 2 03:36 max_user_watches

0 -rw-r--r-- 1 root root 0 Mar 2 03:36 max_user_instances

0 -rw-r--r-- 1 root root 0 Mar 2 03:36 max_queued_events

通过以上显示结果我们应该清楚,CentOS 6.4 x86_64是支持inotify的。

4.inotify可以监控的文件系统事件

inotify是文件系统事件监控机制,是dnotify的有效替代品(dnotify是较早的内核支持的文件监控机制)。inotify是一种强大的、细粒度的、异步的机制,它满足各种各样的文件监控需要,而不仅仅限于安全和性能。

inotify可以监视的文件系统事件包括如下几个方面。

·IN_ACCESS:文件被访问。

·IN_MODIFY:文件被write。

·IN_ATTRIB:文件属性被修改,如chmod、chown、touch等。

·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:宿主文件系统被unmount。

·IN_CLOSE:文件被关闭,等同于(IN_CLOSE_WRITE|IN_CLOSE_NOWRITE)。

·IN_MOVE:文件被移动,等同于(IN_MOVED_FROM|IN_MOVED_TO)。

阅读 ‧ 电子书库

注意

上面所说的文件也包括目录。

5.rsync+inotify企业应用案例

笔者之前的公司的Web应用服务器采用的是集群方案,6台Nginx之间同步代码的方案正是rsync+inotify,这里以3台机器来说明下,即1台rsync服务器,2台rsync客户端机器,此环境跟上面的环境区别较大,大家不要弄混淆了,代码如下所示:

Web-Server :192.168.1.207 rsync 客户端

Web1-Client:192.168.1.204 rsync 服务器端

Web2-Client:192.168.1.205 rsync 服务器端

大家注意下这里的权限分配,不要弄混淆了,Web-Server是作为内容发布的机器,即代码改动是在这台机器上面操作的。这里是作为rsync客户端,并非rsync服务器端。所有机器需要同步的目录均为/data/htdocs/www/images,自动同步顺序均为Web客户端机器向Web-Server端机器同步,我们这里将Web1-Client和Web2-Client配置成rsync的服务器端即可,即Web-Server仅仅只作为rsync客户端。

1)inotify-tools是用来监控文件系统的工具,必须安装在Web-Server(即rsync客户端)机器上,用来监控其文件系统的变化,Web-Client机器不需要安装。

首先开始安装inotify-tools,我们的机器由于提前安装了epel源,这里只需要通过yum命令安装即可,命令比较简单:

yum -y install inotify-tools

2)Web1-Client和Web2-Client机器的rsync服务配置比较容易,大家可以参考上面的内容,下面配置好/etc/rsyncd.conf文件,命令如下所示:

此命令显示内容如下所示:

uid = www

gid = www

user chroot = no

max connections = 200

timeout = 600

pid file = /var/run/rsyncd.pid

lock file = /var/run/rsyncd.lock

log file = /var/log/rsyncd.log

[web1_sync]

path=/data/html/www/images

#web2机器此处配置为

[web2_sync]

ignore errors

read only = no

list = no

hosts allow = 192.168.1.0/255.255.255.0

auth users = www

secrets file = /etc/rsyncd.password

然后重启xinetd即可,命令如下所示:

/etc/init.d/xinetd restart

记得两台Web机器都要配置/etc/rsyncd.passwd文件,rsync的配置过程和原理请大家参考附录前面的内容,这里就不详细说明了,注意/etc/rsyncd.password的文件权限和内容。

3)配置好Web-Server的inotify脚本以后,即可让其开机启动,脚本/root/rsync-inotify.sh内容如下:

#!/bin/bash

src=/data/html/www/images/

des_ip1=192.168.1.204

des_ip2=192.168.1.205

/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f' -e modify,delete,create,attrib $src | while read file

do

rsync -vzrtopg --delete --progress $src www@$des_ip1::web1_sync --password-file=/etc/rsyncd.password

rsync -vzrtopg --delete --progress $src www@$des_ip2::web2_sync --password-file=/etc/rsyncd.password

echo "File Synchronization is Complete!"

done

脚本相关解释如下。

·--timefmt:指定时间的输出格式。

·--format:指定变化文件的详细信息。

这个脚本的作用就是通过inotify监控文件目录的变化,进而触发rsync进行同步操作,由于这个过程是一种主动触发的操作,是通过系统内核来完成的,所以,比起那些遍历整个目录的扫描方式来,效率要高很多。然后我们将此脚本放在/etc/rc.local中,即在最后一行添加相关内容,/etc/rc.local文件改动后的内容如下所示:

/root/rsync-inotify.sh &

4)验证就很容易了,在Web-Server的机器的/data/html/www/images/目录下新建文件,更改文件内容,可以很欣慰地发现,两台Web-Client的机器对应的目录马上也会发生相应的改变,感觉非常快捷方便。

总体说来,rsync+inotify比较适用于没有存储环境的小文件的即时同步更新的工作场景,适合中小型规模的网站。如果Web集群超过10台的话,还是应该考虑自动化配置的方式。