在生产中有一种需求是,当目录下的文件数据发生变化时,就将数据备份到备份服务器上。实现这样的需求需要做到以下两点:
- 利用监控服务 inotify,监控到要同步服务器的目录文件的变化
- 发现目录数据发生变化就利用 rsync 服务将数据发送到备份服务器
因此,利用 rsync+inotify 可实现数据的实时同步。
1. inotify
notify是一种强大的,细粒度的。异步的文件系统事件监控机制,linux内核从2.6.13起,加入了 Inotify支持,通过Inotify可以监控文件系统中
添加、删除,修改、移动
等各种事件。
利用这个内核接口,第三方软件就可以监控文件系统下文件的各种变化情况,而 inotify-tools 正是实施这样监控的软件。
1.1 安装 inotify
前置条件:Linux需要2.6.13以后内核版本才能支持inotify软件。
# 查看内核发行版本
uname -r
- yum安装
yum install -y inotify-tools
- 编译安装
cd /usr/local/src/
wget http://github.com/downloads/rvoicilas/inotify-tools/inotify-tools-3.14.tar.gz
tar zxvf inotify-tools-3.14.tar.gz
cd inotify-tools-3.14
./configure --prefix=/usr/local/inotify
make
make install
1.2 inotify 的组成
inotifywait(主要)
在被监控的文件或目录上等待特定文件系统事件(open close delete等)发生,执行后处于阻塞状态,适合在shell脚本中使用。
inotifywatch
收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计。
在实时同步的时候,主要是利用 inotifywait 对目录进行监控。
1.3 inotifywait 的常用参数
-m 是要持续监视变化
-r 使用递归形式监视目录
-q 减少冗余信息,只打印出需要的信息
-e 指定要监视的事件列表
--timefmt 是指定时间的输出格式
--format 指定文件变化的详细信息
--excludei <pattern> 排除文件或目录时,不区分大小写
close_write 文件或目录关闭,在写入模式打开之后关闭的。
move 文件或目录不管移动到或是移出监控目录都触发事件
create 文件或目录创建在监控目录中
delete 文件或目录被删除在监控目录中
1.4 inotifywait 使用
比如监听 文件的创建
# 一个终端开始监听
inotifywait -mrq /root/rsync_test --timefmt "%d-%m-%y %H:%M" --format "%T %w%f 事件信息: %e" -e create
# 另一个终端创建文件
cd /root/rsync_test
touch 123.txt
# 即可在第一个终端页面看到监听信息
2. rsync
Rsync用于在两个远程计算机之间同步文件和文件夹。它仅通过传输源和目标之间的差异来提供快速的增量文件传输。
Rsync可用于镜像数据,增量备份,在系统之间复制文件,可替代scp,sftp 和 cp 日常等使用的命令。
#安装
yum install rsync
2.1 rsync的常用参数
-v :展示详细的同步信息
-a :归档模式,相当于 -rlptgoD
-r :递归目录
-l :同步软连接文件
-p :保留权限
-t :将源文件的"modify time"同步到目标机器
-g :保持文件属组
-o :保持文件属主
-D :和--devices --specials一样,保持设备文件和特殊文件
-z :发送数据前,先压缩再传输
-H :保持硬链接
-n :进行试运行,不作任何更改
-P same as --partial --progress
--partial :支持断点续传
--progress :展示传输的进度
--delete :如果源文件消失,目标文件也会被删除
--delete-excluded :指定要在目的端删除的文件
--delete-after :默认情况下,rsync是先清理目的端的文件再开始数据同步;如果使用此选项,则rsync会先进行数据同步,都完成后再删除那些需要清理的文件。
--exclude=PATTERN :排除匹配PATTERN的文件
--exclude-from=FILE :如果要排除的文件很多,可以统一写在某一文件中
-e ssh :使用SSH加密隧道传输
2.2 rsync的三种用法
2.2.1 本地文件同步
rsync -avH /root/testfolder/ /tmp/testfolder/
# 如果没有desc目录,会自动创建
2.2.2 远程文件同步—shell方式
# 远程主机文件同步到主机
rsync [选项] USER@HOST:SRC DEST
# 本机文件同步到远程主机
rsync [选项] SRC USER@HOST:DEST
# 推文件
# 从本地传到远端,目标文件会被写成ssh登录用户的属组和属主(如下 www)
rsync -avH /root/rsync_test/ backuptest@your_server_ip:/tmp/rsync_test/
# 使用 ssh 加密隧道方式传输,保障数据的安全性
rsync -avHe ssh /root/rsync_test/ backuptest@your_server_ip:/tmp/rsync_test/
# 拉文件
# 从远端传到本地,只要对目标文件有读的权限,就可以同步到本地
rsync -avH backuptest@your_server_ip:/tmp/rsync_test/ /root/rsync_test/
# 如果远程服务器ssh端口不是默认的22
rsync -avHe "ssh -p 11222" backuptest@your_server_ip:/tmp/rsync_test/ /root/rsync_test/
2.2.3 远程文件同步—daemon方式
# 远程主机文件同步到本地,可使用::或用rsync://指定daemon模式
rsync [选项] USER@HOST::SRC DEST
rsync [选项] **rsync://**USER@HOST/SRC DEST
# 本机文件同步到远程主机
rsync [选项] SRC USER@HOST::DEST
rsync [选项] SRC rsync://USER@HOST/DEST
daemon方式区分客户端和服务端,需要在服务端配置才能正常工作。
2.2.3.1 配置服务端
mkdir /etc/rsync
cd /etc/rsync
vim rsyncd.motd # 写入欢迎文件
vim rsyncd.secrets # 写入密码文件,每一行格式是:用户名:密码
chmod 600 rsyncd.secrets
vim /etc/rsync/rsyncd.conf # 写rsync服务端配置文件
# rsyncd.conf的配置项分全局参数和模块参数,全局参数只有少数几个,一般保持默认即可
# 模块以[模块名]开头,后续参数仅作用于该模块
# 卸载模块外的参数适用于所有模块
# rsyncd.conf文件的指令和值请参考 man rsyncd.conf
# 欢迎文件
motd file = /etc/rsync/rsyncd.motd
# 用户和组id
uid = root
gid = root
# 是否chroot,出于安全考虑建议为yes
use chroot = yes
# 是否记录传输记录
transfer logging = no
# 是否只读,值为true时客户端无法上传
read only = false
# 是否只写,值为true时客户端无法下载
write only = false
# 默认拒绝所有主机连接
hosts deny = *
# 用户名密码文件,每一行格式是:用户名:密码
# 该文件权限必须设置为600,除非strict mode设置为false
secrets file = /etc/rsync/rsyncd.secrets
# 定义名为backup的模块
[backup]
# 模块说明
comment = backup directory
# 模块路径,请求改成自己的
path = /root/rsync_test
# 允许的主机ip
hosts allow = your_client_ip
# 允许的用户名
auth users = backupuser
# 是否允许列出该模块,建议为no
list = no
启动服务,rsync默认监听端口为873,注意服务器安全组的设置。
rsync --daemon --config=/etc/rsync/rsyncd.conf
2.2.3.2 客户端测试
在授权的机器上使用授权用户同步文件:
- rsync -avP 授权用户@服务器ip::backup 本地文件目录
rsync -avP backupuser@your_client_ip::backup /tmp/
上述命令每次执行都需要输入密码,还有指定密码文件的方式。
# 将密码写入文件
echo "backupuser's pwd" > secrets
chmod 600 secrets
# 指定密码文件
rsync -avP --password-file=secrets backupuser@your_server_ip::backup /tmp/
3. 同步脚本
3.1 rsync 排除多个文件和目录
# 举例1,排除文件file1.txt,目录dir1下的所有内容,目录dir2
# vim /tmp/include.txt
*
# vim /tmp/exclude.txt
file1.txt
dir1/*
dir2
# 举例2,排除所有文件,只想同步 .jpg 文件
# vim /tmp/include.txt
*.jpg
# vim /tmp/exclude.txt
*
3.2 inotify 监听 和 rsync 同步脚本
#!/bin/bash
#vim rsync.sh
path=/tmp/testfolder #inotify监控的文件夹
host=your_server_ip #同步的目标服务器
src=/tmp/testfolder/ #rsync同步的文件夹
des=backup #rsync同步的目标模块名
user=rsyncbackuptest #默认用户
include=/tmp/include.txt #同步列表
exclude=/tmp/exclude.txt #不同步列表
#inotify监听文件夹变更
/usr/bin/inotifywait -mq --timefmt '%d/%m/%y %H:%M' --format '%T %w%f%e' -e modify,delete,create,attrib,close_write $path | while read files
do
#rsync同步变更
/usr/bin/rsync -avH --delete --include-from=$include --exclude-from=$exclude --password-file=/tmp/secret $src $user@$host::$des
#记录同步日志
echo "${files} was rsynced" >> /tmp/rsync.log 2>&1
done
3.3 supervisor 管理脚本进程
# vim /etc/supervisord.d/rsync.ini
[program:rsync]
command = sh /root/rsync.sh
process_name=%(program_name)s_%(process_num)02d
numprocs = 1
directory = /root
redirect_stderr = true
stdout_logfile_maxbytes = 20MB
stdout_logfile_backups = 20
stdout_logfile = /var/log/supervisor_rsync_test.log
stopasgroup = true
killasgroup = true
stopsignal = KILL
参考: