数据镜像备份工具rsync + inotify
一、rsync介绍:
rsync是Unix下的一款应用软件,它能同步更新两处计算机的文件与目录,并适当利用差分编码以减少数据传输。rsync中一项与其他大部分类似程序或协定中所未见的重要特性是镜像对每个目标只需要一次传送。rsync可拷贝/显示目录属性,以及拷贝文件,并可选择性的压缩以及递归拷贝。
在常驻模式(daemon mode)下,rsync默认监听TCP端口873,以原生rsync传输协定或者通过远程shell如RSH或者SSH伺服文件。SSH情况下,rsync客户端运行程序必须同时在本地和远程机器上安装。
rsync同时也是Linux系统下的数据镜像备份工具,通过rsync可以将本地系统数据通过网络备份到任何远程主机上,rsync有如下特性:
1.可以镜像保存整个目录树和文件系统
2.可以增量同步数据,文件传输效率高,因而同步时间很短。
3.可以保持原有文件的权限、时间等属性。
4.加密传输数据,保证了数据的安全性。
1.下载与安装rsync软件
rsync的主页:http://rsync.samba.org/download.html,
[root@server ~]# rpm -qa | grep rsync
[root@server ~]# rpm -e rsync
[root@server ~]# tar zxf rsync-3.0.9.tar.gz
[root@server ~]# cd rsync-3.0.9
[root@server rsync-3.0.9]# ./configure && make && make install
2.rsync的应用模式
(1)本地shell模式,主要用于复制指定目录到另一个目录。
[root@server ~]# rsync -av /root/ /backup
以上命令中选项“-a”为“--archive”(归档模式),表示以递归的方式传输文件,并保持所有文件的属性。“-v”为“verbose”,表示输出详细的信息。
(2)远程shell模式,rsync可以把指定的本地目录复制到远程主机。会在远程主机的root目录下创建一个目录。
[root@server ~]# rsync -av /root/ 192.168.4.141:backup
(3)rsync列表模式,与ls命令有相似的功能。
[root@server ~]# rsync -a 192.168.4.141:backup
(4)服务器模式,这种模式是基于C/S模式,在这种模式下,rsync在后台启用一个守护进程,这个守护进程在rsync服务端永久运行,用于接收文件传输请求,因此,客户端既可以把文件发送给守护进程,也可以像守护进程请求文件。rsync的服务器模式很适合作为异地的中心备份服务器或数据异地存储库来使用。
3.搭建远程容灾备份系统
如:某公司的业务服务系统的底层的操作系统是linux,业务系统每天会有大量数据增加。为了保证数据安全,需要建立一个远程容灾系统,将业务系统的数据在每天2:00备份到远程容灾服务器上。
分析:由于数据量较大,如果每天做完整备份,显然备份效率低下,所以每天只能做增量备份,即备份当天增加的数据,当业务系统出现故障后,可以通过备份过的数据尽可能恢复数据,将损失降到最低。
(1)系统环境:
操作系统:Red Hat Enterprise Linux Server release 5.5 (Tikanga)
内核版本:linux 2.6.18-194.el5
Server端的IP地址:192.168.4.141
Client端(即远程备份端)的IP地址:192.168.4.180
(2)Server端配置:
rsync的配置文件为/etc/rsyncd.conf,在安装rsync完成后默认没有这个文件需要建立。rsyncd.conf文件有一个或多个模块结构组成,包括全局参数和模块参数。
[root@server ~]# vim /etc/rsyncd.conf
# option setting
uid = nobody
gid = nobody
use chroot = no
max connections = 10
strict modes = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
# module setting
[example]
comment = example file
ignore errors
read only = no
write only = no
path = /opt/app/
hosts allow = *
hosts deny = 192.168.4.131
list = false
uid = root
gid = root
auth users = backup
secrets file = /etc/rsync.pass
# uid,此选项指定当该模块传输文件时守护进程应该具有的用户ID,默认值是"nobody".
# gid,此选项指定当该模块传输文件时守护进程应该具有的用户组ID,默认值是"nobody".
# max connections,此选项指定模块的最大并发连接数量,以保护服务器。超过限制的连接请求将被暂时限制。默认值是0,即没有限制。
# strict modes,此选项指定是否检查口令文件的权限,yes为检查口令文件权限,反之为no。如果设置为yes,密码文件的权限必须为root用户权限。
# pid file,此选项用来指定rsync守护进程对应的PID文件路径。
# lock file,此选项用来指定支持max connections的锁文件,默认值是/var/run/rsyncd.lock。
# log file,此选项指定了rsync的日志输出文件路径。
# [example],表示定义一个模块的开始,example就是对应模块的名称。
# path,此选项用来指定需要备份的文件或目录,是必须设置的项。这里指定的目录为/opt/app/。
# ignore errors,表示可以忽略一些无关的I/O错误。
# read only,设置为no表示客户端可以上传文件,设置为yes表示只读。
# write only,设置为no表示客户端可以下载文件,设置为yes表示不能下载。
# list,此选项用于设定当客户端请求可以使用的模块列表时,该模块是否被列出。默认值是true。
# auth users,此选项用来定义可以连接该模块的用户名,多个用户以空格或逗号分隔开。该处的用户无本地系统用户无关。
# secrets file,此选项用于指定一个包含"用户名:密码"格式的文件。用户名就是"auth users"选项定义的用户。服务端的密码文件可以设置注释加以解释说明。
[root@server ~]# vim /etc/rsync.pass
# Set backup user and user's password.
backup:123.com
[root@server ~]# chmod 600 /etc/rsync.pass
(3)在服务端启动守护进程。
[root@server ~]# /usr/local/bin/rsync –daemon
[root@server ~]# echo "/usr/local/bin/rsync --daemon" >> /etc/rc.local
[root@server ~]# ps -ef | grep rsync
root 3200 1 0 20:44 ? 00:00:00 /usr/local/bin/rsync --daemon
root 3204 3066 0 20:45 pts/0 00:00:00 grep rsync
[root@server ~]# netstat -antupl | grep rsync
tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN 3200/rsync
tcp 0 0 :::873 :::* LISTEN 3200/rsync
(4)在客户端上配置:
在客户端上不用做配置文件操作,只需要执行rsync同步操作即可。为了方便在同步过程中不用输入密码验证,需要在客户端创建一个secrets file,该文件的内容必须要服务端rsyncd.conf文件中“auth users”选项中指定用户密码,文件的路径可以随意指定。
[root@client ~]#/usr/local/bin/rsync -vzrtopg --delete --progress --exclude '*access*' --exclude 'debug*' [email protected]::example /backup/example --password-file=/etc/rsync.pass
以上命令备份的命令可以写成脚本:
[root@rsapp2 ~]# cat /opt/script/backup_rsync.sh
#!/bin/bash
# Set local backup destination directory.
PATH=/backup/example/
# Set need backup host and module name,you can see node module in file of /etc/rsyncd.conf .
host=192.168.4.141
module=example
# Set backup users's password file.
PASS_FILE=/etc/rsync.pass
if [ -d "$PATH" ]; then
echo "The named $PATH of backup directory alreadly exits."
else
echo "The named $PATH of backup directory not exits."
/bin/mkdir -p $PATH
fi
/usr/local/bin/rsync -vzrtopg --delete --progress --exclude "*access*" --exclude "debug*" backup@$host::$module $PATH --password-file=$PASS_FILE
[root@client ~]# chmod 750 /opt/script/backup_rsync.sh
添加到计划任务中去:
[root@client ~]# crontab -u root -e
00 2 * * * /opt/script/backup_rsync.sh
认证的密码文件及内容:
[root@client ~]# vim /etc/rsync.pass
123.com #注意此文件里的内容只能是密码,不能含有注释行,否则会报错提示:认证失败。
[root@client ~]# chmod 600 /etc/rsync.pass
对以上的命令选项每个参数的含义介绍如下:
“--vzrtopg”选项中v是“—verbose”,即详细模式输出,z表示“--compress” 即对备份的文件在传输时进行压缩处理,r表示“--recursive”,也就是对子目录以递归模式处理。t即“--times”,用来保持文件时间信息,o即“--owner”用来保持文件属主信息。p即“--perms”用来保持文件权限,g即“--group”用来保持文件的属组信息。
“--delete”选项指定以rsync服务端为基准进行数据镜像同步,也就是要保持rsync服务端目录与客户端目录的完全一致性。在这里也就是以A服务器为基准进行同步。
“--progress”选项用于显示数据镜像同步的过程。
“[email protected]::example” 表示对服务器192.168.4.141中的example模块进行备份,也就是指定备份的模块,backup表示使用“backup”这个用户对该模块进行备份。
“/backup/example”用于指定备份文件在客户端机器上的存放路径,也就是将备份的文件存放在备份机的/ixdba.net目录下。
“--password-file=/etc/rsync.pass”用来指定客户机上存放的密码文件位置,这样在客户端执行同步命令时就无需输入交互密码了,注意,这个密码文件的名称和位置可以随意指定,但是在客户机上必须存在此文件,文件的内容仅仅为备份用户的密码,这里指的是backup的密码。
如果配置没有错误,接下来rsync将自动去服务端将需要备份的数据同步到客户端。rsync指令在客户端执行完成数据的同步后,将自动停止,以后如果在服务端目录下有新增数据时,客户端不会自动将数据同步过去,此时,还需要再次执行rsync命令组合进行数据同步,因此,rsync方式的数据备份是需要触发同步指令才能完成。
触发同步指令的方式有很多种,例如可以将同步指令放入客户端系统的crontab守护进程,设定同步时间,然后让Linux去触发同步指令,自动完成数据备份。这种数据备份方式可以用于数据安全性要求不是很高的业务系统上。
在这种方式下,服务端和客户端的数据在两次同步的时间间隔内,可能出现不一致现象。而对于数据安全性要求极高的业务系统,这种备份方式就不能满足要求了,这些业务要求服务端和客户端的数据要做到实时同步,不过幸运的是,Linux内核提供了inotify文件系统监控机制,通过inotify与rsync的组合,完全可以做到rsync服务端和客户端数据的实时同步。
二、inotify介绍
inotify 是一种强大的、细粒度的、异步的文件系统事件监控机制,linux内核从2.6.13起,加入了Inotify支持,通过Inotify可以监控文件系统中添加、删除,修改、移动等各种细微事件,利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而inotify-tools就是这样的一个第三方软件。
在上面章节中,我们讲到,rsync可以实现触发式的文件同步,但是通过crontab守护进程方式进行触发,同步的数据和实际数据会有差异,而inotify可以监控文件系统的各种变化,当文件有任何变动时,就触发rsync同步,这样刚好解决了同步数据的实时性问题。
由于inotify特性需要Linux内核的支持,在安装inotify-tools前要先确认Linux系统内核是否达到了2.6.13以上,如果Linux内核低于2.6.13版本,就需要重新编译内核加入inotify的支持,也可以用如下方法判断,内核是否支持inotify:
[root@server ~]# uname -r
2.6.18-194.el5
[root@server ~]# ls -lh /proc/sys/fs/inotify
-rw-r--r-- 1 root root 0 Nov 23 21:38 max_queued_events
-rw-r--r-- 1 root root 0 Nov 23 21:38 max_user_instances
-rw-r--r-- 1 root root 0 Nov 23 21:38 max_user_watches
[root@server ~]# tar -zxf inotify-tools-3.14.tar.gz
[root@server ~]# cd inotify-tools-3.14
[root@server inotify-tools-3.14]# ./configure && make && make install
[root@server inotify-tools-3.14]# ls -lh /usr/local/bin/inotifywa*
inotify-tools安装完成后,会生成inotifywait和inotifywatch两个指令,其中,inotifywait用于等待文件或文件集上的一个特定事件,它可以监控任何文件和目录设置,并且可以递归地监控整个目录树。
inotifywatch用于收集被监控的文件系统统计数据,包括每个inotify事件发生多少次等信息。
inotifywait是一个监控等待事件,可以配合shell脚本使用它,下面介绍一下常用的一些参数:
-m,即--monitor,表示始终保持事件监听状态。
-r,即--recursive,表示递归查询目录。
-q,即--quiet,表示打印出监控事件。
-e, 即--event,通过此参数可以指定要监控的事件,常见的事件有modify、delete、create、attrib等。
案例描述:
一个web发布系统,后端采用负载均衡集群部署方案,有一个负载调度节点、两个服务节点和一个内容发布节点构成,内容发布节点负责将用户发布的数据生成静态页面,同时将静态网页传输到两台服务节点,而负载调度节点负责将用户请求根据负载算法调度到相应的服务节点,实现用户访问。用户要求在前端访问到的网页数据始终是最新的、一致的。
解决方案:
为了保证用户访问到的数据一致性和实时性,必须保证三个服务节点与内容发布节点的数据始终是一致的,这就需要通过文件同步工具来实现,这里采用rsync,同时又要保证数据是实时的,这就需要inotify,即:使用inotify监视内容发布节点文件的变化,如果文件有变动,那么就启动rsync,将文件实时同步到两个服务节点。
系统环境介绍,所有服务器都采用linux操作系统,具体配置如下:
节点名称 |
内核版本 |
说明 |
IP地址 |
网页存放路径 |
server |
2.6.18-194.el5 |
内容发布节点 |
192.168.4.132 |
/var/www/html/aaa |
rsapp1 |
2.6.18-194.el5 |
服务节点1 |
192.168.4.141 |
/var/www/html/abc |
rsapp2 |
2.6.18-194.el5 |
服务节点2 |
192.168.4.142 |
/var/www/html/bcd |
1.安装rsync与inotify-tools
inotify-tools是用来监控文件系统变化的工具,因此必须安装在内容发布节点,服务节点不需要安装inotify-tools,另外需要在server、rsapp1、rsapp2节点上安装rsync,由于安装非常简单,这里不在讲述。
在这个案例中,内容发布节点(即server)充当了rsync客户端的角色,而两个服务节点充当了rsync服务器端的角色,整个数据同步的过程是从客户端向服务端推送数据的过程。
2.配置服务节点:
(1)服务节点1
[root@rsapp1 ~]# vim /etc/rsyncd.conf
# option setting.
uid = nobody
gid = nobody
use chroot = no
max connections = 10
strict modes = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
# module setting.
[example1]
path = /var/www/html/abc/
comment = example1 file
ignore errors
read only = no
write only = no
hosts allow = 192.168.4.132
#hosts deny = 192.168.4.131
list = false
uid = root
gid = root
auth users = backup1
secrets file = /etc/rsync.pass
[root@rsapp1 ~]# vim /etc/rsync.pass
# set backup users and password.
backup1:1234.com
[root@rsapp1 ~]# chmod 600 /etc/rsync.pass
(2)服务节点2
[root@rsapp2 ~]# cat /etc/rsyncd.conf
# option setting.
uid = nobody
gid = nobody
use chroot = no
max connections = 10
strict modes = yes
pid file = /var/run/rsyncd.pid
lock file = /var/run/rsyncd.lock
log file = /var/log/rsyncd.log
# module setting.
[example2]
path = /var/www/html/bcd/
comment = example2 file
ignore errors
read only = no
write only = no
hosts allow = 192.168.4.132
#hosts deny = 192.168.4.131
list = false
uid = root
gid = root
auth users = backup2
secrets file = /etc/rsync.pass
[root@rsapp2 ~]# cat /etc/rsync.pass
# Set backup user and password.
backup2:12345.com
[root@rsapp2 ~]# chmod 600 /etc/rsync.pass
## 建议将example1、example2模块的认证密码设为相同,方便后面认证文件定义。
(3)在app1、app2上面分别做以下操作:
[root@app1 ~]# /usr/local/bin/rsync --daemon
[root@app1 ~]# netstat -antupl | grep rsync
tcp 0 0 0.0.0.0:873 0.0.0.0:* LISTEN 2735/rsync
tcp 0 0 :::873 :::* LISTEN 2735/rsync
[root@app1 ~]# ps -ef | grep rsync
root 2735 1 0 00:08 ? 00:00:00 /usr/local/bin/rsync --daemon
root 2741 2633 0 00:08 pts/0 00:00:00 grep rsync
[root@app1 ~]# echo "/usr/local/bin/rsync --daemon" >> /etc/rc.local
3.配置内容发布节点:
[root@server ~]# vim /opt/script/inotifyrsync.sh
#!/bin/bash
host1=192.168.4.141
host2=192.168.4.142
# set local need backup source directory.
src=/var/www/html/aaa/
# set module name,you can see every node module in file of /etc/rsyncd.conf .
dst1=example1
dst2=example2
# set backup user.
user1=backup1
user2=backup2
# set backup users's password file.(local)
pass_file_app1=/etc/authkey/rsync_app1.pass
pass_file_app2=/etc/authkey/rsync_app2.pass
/usr/local/bin/inotifywait -mrq --timefmt '%d/%m/%y %H:%m' --format '%T %w%f%e' -e modify,delete,create,attrib $src \
| while read files
do
/usr/local/bin/rsync -vzrtopg --delete --progress --password-file=$pass_file_app1 $src $user1@$host1::$dst1
/usr/local/bin/rsync -vzrtopg --delete --progress --password-file=$pass_file_app2 $src $user2@$host2::$dst2
echo "$files was rsynced" >> /tmp/rsync.log 2>&1
done
[root@server ~]# vim /etc/authkey/rsync_app1.pass
1234.com
[root@server ~]# vim /etc/authkey/rsync_app2.pass
12345.com
## 从以上两个文件中可以看出认证文件的密码不一样,在同步脚本中“--password-file”选项的认证密码文件设置就比较麻烦,而且也还容易弄错,所以建议将example1、example2模块的认证密码都设为相同的。
[root@server ~]# chmod 600 /etc/rsync.pass
[root@server ~]# chmod 755 /opt/script/inotifyrsync.sh
[root@server ~]# /opt/script/inotifyrsync.sh &
[root@server ~]# echo "/opt/script/inotifyrsync.sh &" >> /etc/rc.local
脚本相关解释如下:
--timefmt:指定时间的输出格式。
--format:指定变化文件的详细信息。
这两个参数通常一般配合使用。
这个脚本的作用就是通过inotify监控文件目录的变化,进而触发rsync进行同步操作,由于这个过程是一种主动触发操作,通过系统内核完成的,所以执行效率很高。
有时会遇到这样的情况:向inotify监控的目录(/var/www/html/aaa)写入一个很大文件时,由于写入这个大文件需要一段时间,此时inotify就会持续不停的输出该文件被更新的信息, 这样就会持续不停的触发rsync去执行同步操作,占用了大量系统资源,那么针对这种情况,最理想的做法是等待文件写完后再去触发rsync同步。 在这种情况下,可以修改inotify的监控事件,即:“-e close_write,delete,create,attrib”。
4.测试rsync+inotify实时同步功能
当所有配置完成后,可以在网页发布节点的/var/www/html/aaa目录下添加、删除或者修改某个文件,然后到两个服务节点对应的目录(/var/www/html/abc、/var/www/html/bcd)查看文件是否跟随网页发布节点的目录/var/www/html/abc下文件发生变化,如果你看到两个服务节点对应的目录文件跟着内容发布节点目录文件同步变化,那么我们这个业务系统就配置成功了。在前台运行/opt/script/inotifyrsync.sh脚本时,会相信看到同步的信息。