数据实时同步:inotify + rsync 实现数据实时同步
1 数据实时同步
在生产环境中,某些场景下,要将数据或文件进行实时同步,保证数据更新后其它节点能立即获得最新的数据。
数据同步的两种方式
PULL:拉,使用定时任务的方式配合同步命令或脚本等,从指定服务器上将数据同步到本地,一般是周期性定时同步
PUSH:推,如果当前机器上的数据或文件发生更新了,立即推送到指定的节点上,可以做到实时同步
1.1 实时同步的实现方式
-
inotify + rsync
-
sersync
1.2 inotify + rsync 实现数据实时同步
实现原理
利用内核中的 inotify 监控指定目录,当目录中的文件或数据发生变化时,立即调用 rsync 服务将数据推送到远程主机上。
1.2.1 inotify 服务
inotify 是一个内核用于通知用户空间程序文件系统变化的机制,在监听到文件系统发生变化后,会向相应的应用程序发送事件,如文件增加,修改,删除等事件发生后可以立即让用户空间知道。
https://github.com/rvoicilas/inotify-tools #项目地址
inotify 是内核中的功能,在2.6.13版本的内核开始都默认存在。
[root@ubuntu ~]# grep -i inotify /boot/config-5.15.0-76-generic
CONFIG_INOTIFY_USER=y
[root@rocky ~]# grep -i inotify /boot/config-4.18.0-372.9.1.el8.x86_64
CONFIG_INOTIFY_USER=y
inotify 内核参数
[root@ubuntu ~]# ls -l /proc/sys/fs/inotify
total 0
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_queued_events
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_user_instances
-rw-r--r-- 1 root root 0 Jul 11 09:46 max_user_watches
#inotify 事件队列最大长度,如值太小会出现 Event Queue Overflow 错误,默认 16384,生产环境建议调大,比如 327679
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_queued_events
16384
#每个用户创建inotify实例最大值,默认值 128
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_user_instances
128
#每个inotify实例可以监视的文件的总数量
[root@ubuntu ~]# cat /proc/sys/fs/inotify/max_user_watches
14165
#一个用户可以最多开128个inotify实例,每个实例最多可以监控14165个文件
内核参数如果需要修改,可以配置文件
[root@ubuntu ~]# cat /etc/sysctl.conf
fs.inotify.max_queued_events=66666
fs.inotify.max_user_instances=256
fs.inotify.max_user_watches=100000
[root@ubuntu ~]# sysctl -p
fs.inotify.max_queued_events = 66666
fs.inotify.max_user_instances = 256
fs.inotify.max_user_watches = 100000
安装软件
inotify 是内核中的功能模块,只能通过调用API接口的形式使用其功能,我们可以通过相关软件来对其进行操作,能实现内核中 inotify 调用的软件主要有以下几个:
inotify-tools,sersync,lrsyncd
#centos系列中该软件来自于 epel 源
[root@ubuntu ~]# apt install inotify-tools
#主要工具
/usr/bin/fsnotifywait #fsnotify监控工具,fsnotify 是 inotify 的新版本
/usr/bin/fsnotifywatch #fsnotify统计工具
/usr/bin/inotifywait #实时监控指定目录的所有事件,在被监控的文件或目录上等待特定事件发生(open,close,write...)
/usr/bin/inotifywatch #收集被监控的文件系统使用的统计数据,指文件系统事件发生的次数统计
命令格式
inotifywait [ options ] file1 [ file2 ] [ file3 ] [ ... ]
#常用选项
-h|--help #显示帮助
@<file> #排除指定文件
--exclude <pattern> #不监控指定的文件或目录,正则匹配
--excludei <pattern> #不监控指定的文件或目录,正则匹配,不区分大小写
--include <pattern> #仅监控指定的文件或目录,正则匹配
--includei <pattern> #仅监控指定的文件或目录,正则匹配,不区分大小写
-m|--monitor #始终保持监听,直到超时
-d|--daemon #以守护进程方式执行,配合-o使用
-P|--no-dereference #不跟随软链接
-r|--recursive #对目录递归监控,即监控目录内所有内容
--fromfile <file> #从文件中读取要监控的内容
-o|--outfile <file> #将执行结果输出到指定文件
-s|--syslog #错误输出到syslog,而不是标准错误输出
-q|--quiet #简短输出,仅输出事件信息
-qq #禁用输出
--format <fmt> #指定输出格式
--no-newline #不换行输出,配合--format字段
--timefmt <fmt> #指定时间输出格式
-c|--csv #以CSV格式输出
-t|--timeout <seconds> #指定超时时长,值为0则永远不超时
-e|--event <event1> #只监听指定事件,默认监听所有事件
# --format 选项可用字段
%T #输出时间格式中定义的时间格式信息,通过 --timefmt option 语法格式指定时间信息
%w #事件出现时,监控文件或目录的名称信息,相当于dirname
%f #事件出现时,将显示监控目录下触发事件的文件或目录信息,否则为空,相当于basename
%e #显示发生的事件信息,不同的事件默认用逗号分隔
%Xe #显示发生的事件信息,不同的事件指定用X进行分隔
# --timefmt 选项可用字段
%Y #年份信息,包含世纪信息
%y #年份信息,不包括世纪信息
%m #显示月份,范围 01-12
%d #每月的第几天,范围是 01-31
%H #小时信息,使用 24小时制,范围 00-23
%M #分钟,范围 00-59
%S #秒,范例 0-60
# -e 选项可以指定的事件
access #文件或目录内容被读取
modify #内容发生变化
attrib #属性发生变化
close_write #写入模式打开后关闭
close_nowrite #只读打开后关闭
close #关闭事件,无关模式
open #打开事件,无关模式
moved_to #文件或目录被移动到监控的目录中
moved_from #文件或目录从监控的目录中被移动
move #文件或目录不管移动到或是移出监控目录都触发事件
move_self #被移动之后同名文件不再被监控
create #创建文件或目录
delete #文件或目录被删除
delete_self #被删除之后同名文件不再被监控
unmount #取消挂载
只监控一个事件
[root@ubuntu ~]# tree /data/
/data/
├── dir1
└── dir2
2 directories, 0 files
#开始监控
[root@ubuntu ~]# inotifywait /data/
Setting up watches.
Watches established.
#在另一个终端中执行
[root@ubuntu ~]# ls /data/
dir1 dir2
#提示 open事件并退出
[root@ubuntu ~]# inotifywait /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR
持续监控
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
#另一个终端操作
[root@ubuntu ~]# ls /data
dir1 dir2
[root@ubuntu ~]# ls /data/dir1
[root@ubuntu ~]# touch /data/test.txt
#查看监控,一条命令可能有多个事件
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR
/data/ ACCESS,ISDIR
/data/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR
/data/ OPEN,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
/data/ CREATE test.txt
/data/ OPEN test.txt
/data/ ATTRIB test.txt
/data/ CLOSE_WRITE,CLOSE test.txt
递归监控
[root@ubuntu ~]# ls /data/dir1/
[root@ubuntu ~]# touch /data/dir1/test.txt
[root@ubuntu ~]# rm -f /data/dir1/test.txt
#无法监控 touch 和 rm
[root@ubuntu ~]# inotifywait -m /data/
Setting up watches.
Watches established.
/data/ OPEN,ISDIR dir1
/data/ ACCESS,ISDIR dir1
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
[root@ubuntu ~]# ls /data/dir1/
[root@ubuntu ~]# touch /data/dir1/test.txt
[root@ubuntu ~]# rm -f /data/dir1/test.txt
#递归监控
[root@ubuntu ~]# inotifywait -m -r /data/
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
/data/ OPEN,ISDIR dir1
/data/dir1/ OPEN,ISDIR
/data/ ACCESS,ISDIR dir1
/data/dir1/ ACCESS,ISDIR
/data/ ACCESS,ISDIR dir1
/data/dir1/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR dir1
/data/dir1/ CLOSE_NOWRITE,CLOSE,ISDIR
/data/dir1/ CREATE test.txt
/data/dir1/ OPEN test.txt
/data/dir1/ ATTRIB test.txt
/data/dir1/ CLOSE_WRITE,CLOSE test.txt
/data/dir1/ DELETE test.txt
将结果输出到文件
[root@ubuntu ~]# inotifywait -m -r /data/ -o inotify.txt
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
[root@ubuntu ~]# ls /data/
dir1 dir2 test.txt
#查看结果文件
[root@ubuntu ~]# cat inotify.txt
/data/ OPEN,ISDIR
/data/ ACCESS,ISDIR
/data/ CLOSE_NOWRITE,CLOSE,ISDIR
从文件中读取要监控的内容
[root@ubuntu ~]# cat a.txt
/data/
[root@ubuntu ~]# inotifywait -rm --fromfile a.txt
Setting up watches. Beware: since -r was given, this may take a while!
Watches established.
后台守护执行,并指定输出格式
[root@ubuntu ~]# inotifywait -drq /data/ -o inotify.log --timefmt "%Y-%m-%d %H:%M:%S" --format "%T %w %f event: %e"
[root@ubuntu ~]# cat inotify.log
2025-01-12 14:45:53 /data/ event: OPEN,ISDIR
2025-01-12 14:45:53 /data/ event: ACCESS,ISDIR
2025-01-12 14:45:53 /data/ event: CLOSE_NOWRITE,CLOSE,ISDIR
指定输出格式,且只记录特定事件
[root@ubuntu ~]# ls /data/
dir1 dir2 test.txt
[root@ubuntu ~]# touch /data/test.log
[root@ubuntu ~]# touch /data/test.log
[root@ubuntu ~]# rm -f /data/test.log
[root@ubuntu ~]# inotifywait -mrq /data/ --timefmt "%F %H:%M:%S" --format "%T%w%f event:%;e" -e create,delete,moved_to,close_write,attrib
2025-01-12 14:58:03 /data/test.log event:CREATE
2025-01-12 14:58:03 /data/test.log event:ATTRIB
2025-01-12 14:58:03 /data/test.log event:CLOSE_WRITE;CLOSE
2025-01-12 14:58:06 /data/test.log event:ATTRIB
2025-01-12 14:58:06 /data/test.log event:CLOSE_WRITE;CLOSE
2025-01-12 14:58:09 /data/test.log event:DELETE
1.2.2 rsync 服务
rsync 常用于作为 linux系统下的数据镜像备份工具,实现远程同步,支持本地复制,或者与其他SSH、rsync主机同步数据,支持增量备份,配合任务计划,rsync能实现定时或间隔同步,配合 inotify 或 sersync,可以实现触发式的实时数据同步。
http://rsync.samba.org/ #官方网站
安装软件
[root@ubuntu ~]# apt install rsync
命令格式
#Local
rsync [OPTION]... SRC [SRC]... DEST #本地文件同步
#Access via remote shell
rsync [OPTION]... [USER@]HOST:SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST #PUSH 推,将本地文件推送到远程主机上
#Access via rsync daemon:
rsync [OPTION]... [USER@]HOST::SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST] #PULL 拉,将远程主机上的文件拉到本地
rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST #PUSH 推,将本地文件推送到远程主机上
rsync [OPTION]... SRC [SRC]... rsync://[USER@]HOST[:PORT]/DEST #PUSH 推,将本地文件推送到远程主机上
rsync 有三种工作方式
-
本地文件系统上实现同步。命令行语法格式为上述 "Local" 段的格式
-
本地主机使用远程shell和远程主机通信。命令行语法格式为上述 "Access via remote shell" 段的格式,使用的用户名和密码是 Linux系统的用户名和密码
-
本地主机通过网络套接字连接远程主机上的 rsync daemon。命令行语法格式为上述 "Access via rsync daemon" 段的格式,使用的用户名和密码是 rsync 服务中配置的用户名和密码
前两者的本质是通过本地或远程shell,而第3种方式则是让远程主机上运行 rsyncd 服务,使其监听在一个端口上,等待客户端的连接,此种方式使用的 rsync 的专有协议。
常用选项
--verbose|-v #显示详细过程,最多可以 -vvvv
--quiet|-q #不输出错误信息
--archive|-a #归档模式,保留文件属性
--recursive|-r #递归
--backup|-b #如果目标文件存在,先做备份,默认备份后缀是 ~
--backup-dir=DIR #指定备份目录
--suffix=SUFFIX #指定备份后缀
--update|-u #仅在源mtime比目标已存在文件的mtime新时才拷贝,该选项是接收端判断的,不会影响删除行为
--links|-l #传输软链接文件,而不是传输其指向的文件
--copy-links|-L #跟随软链接,传输其指向的目标文件或目录
--perms|-p #保留权限(不包括特殊权限)
--owner|-o #保持owner属性
--group|-g #保持group属性
-D #传输设备文件和特殊文件,同 --devices --specials
--times|-t #保留mtime属性
--dry-run|-n #测试模式,不实际传输,常合 -vvvv 配合查看细节
--whole-file|-W #不使用增量传输,而使用全量传输,在网络带宽高于磁盘带宽时,该选项比增量传输更高效
--rsh=COMMAND|-e #指定所要使用的远程shell程序,默认为ssh
--existing #只更新远端已存在的文件,远端不存在的文件不传输。使用相对路径时如果上层目录不存在也不会传输
--ignore-existing #只传输远程主机不存在的文件
--remove-source-files #删除己传输成功的源文件
--del #在传输中删除,同 --delete-during
--delete #文件传输时,删除DEST中在SRC 中不存在的文件
--delete-before #传输开始前先删除
--delete-during #在传输过程中删除
--delete-delay #在传输中确定要删除的文件,传输结束后删除
--delete-after #传输结束后再删除
--delete-excluded #删除远程主机上在此项中指定的文件
--force #强制删除目录,哪怕不为空
--max-delete=NUM #最多删除NUM个文件
--max-size=SIZE #限制rsync传输的最大文件大小,可以使用单位后缀,可以写小数值
--min-size=SIZE #限制rsync传输的最小文件大小。可用于禁止传输小文件或垃圾文件,可以写小数值
--size-only #默认传输有变化的文件,默认检查文件大小变化和 mtime,此项表示只检查文件大小变化
--compress|-z #压缩传输
--exclude=PATTERN #用正则来指定排除规则来排除不需要传输的文件
--exclude-from=FILE #从文件中读取不需要被传送的文件
--include=PATTERN #用正则来指定要传输的文件
--include-from=FILE #从文件中读取要传输的文件
--port=PORT #连接daemon时使用的端口号,默认为873端口
--human-readable|-h #以人类友好的格式显示相关信息
--progress #显示进度条
-P #显示进度条,同 --partial --progress
--password-file=FILE #daemon模式时密码文件,读取密码非交互式操作 这不是远程shell认证的密码,而是rsync模块认证的密码
--version|-V #显示版本信息
--help|-h (*) #显示帮助信息
实现 rsync daemon 服务
主机清单
IP | 角色 |
10.0.0.208 | rsync-server |
10.0.0.206 | rsync-client |
#服务端以守护进程运行
[root@ubuntu ~]# systemctl enable --now rsync.service
#启动失败,因为 /etc/rsyncd.conf 配置文件不存在
[root@ubuntu ~]# systemctl status rsync.service
#创建空配置文件
[root@ubuntu ~]# touch /etc/rsyncd.conf
#启动服务
[root@ubuntu ~]# systemctl start rsync.service
#查看服务状态,运行中
[root@ubuntu ~]# systemctl status rsync
#监听 873 端口
[root@ubuntu ~]# ss -tunlp | grep rsync
#客户端连接测试
[root@ubuntu ~]# rsync rsync://10.0.0.208
[root@ubuntu ~]# echo $?
0
#修改服务端配置,指定共享目录
[root@ubuntu ~]# cat /etc/rsyncd.conf
[dir1]
path=/data/dir1/
read only=no
#重启服务
[root@ubuntu ~]# systemctl restart rsync.service
#查看服务端目录
[root@ubuntu ~]# tree /data/
/data/
└── dir1
1 directory, 0 files
#客户端再次测试,可以看到内容
[root@ubuntu ~]# rsync rsync://10.0.0.208
dir1
#两种写法都可以, :: 表示走rsync协议
[root@ubuntu ~]# rsync 10.0.0.208::
dir1
#传输文件到远程失败,此处的 root 是指rsync服务的用户,当前服务端并没有配置此信息,默认会被映射成 nobody
[root@ubuntu ~]# rsync /etc/fstab root@10.0.0.208::dir1
rsync: [receiver] mkstemp "/.fstab.tBlxU2" (in dir1) failed: Permission denied (13)
rsync error: some files/attrs were not transferred (see previous errors) (code 23) at main.c(1338) [sender=3.2.7]
#在服务端配置权限
[root@ubuntu ~]# setfacl -m u:nobody:rwx /data/dir1/
#客户端再次测试,上传成功,现在使用的是匿名连接
[root@ubuntu ~]# rsync /etc/fstab root@10.0.0.208::dir1
[root@ubuntu ~]# rsync /etc/issue tom@10.0.0.208::dir1 #tom 用户在服务端并不存在
#服务端查看,属主属组都是 nobody
[root@ubuntu ~]# ls -l /data/dir1/
total 8
-rw-r--r-- 1 nobody nogroup 771 Jul 12 00:02 fstab
-rw-r--r-- 1 nobody nogroup 24 Jul 12 00:04 issue
#指定映射账号,指定日志文件,指定远程连接用户名和密码,禁用匿名连接
[root@ubuntu ~]# cat /etc/rsyncd.conf
uid=root
gid=root
max connections=0
log file=/var/log/rsyncd.log
pid file=/var/run/rsyncd.pid
lock file=/var/run/rsyncd.lock
[dir1]
path=/data/dir1/
comment=rsync dir1
read only=no
auth users=rsyncer
secrets file=/etc/rsyncd.pwd
#密码文件
[root@ubuntu ~]# cat /etc/rsyncd.pwd
123456
#重启服务
[root@ubuntu ~]# systemctl restart rsync.service
#客户端再次测试,匿名非匿名都报错
[root@ubuntu ~]# rsync 10.0.0.208::dir1
Password:
@ERROR: auth failed on module dir1
rsync error: error starting client-server protocol (code 5) at main.c(1863) [Receiver=3.2.7]
[root@ubuntu ~]# rsync rsyncer@10.0.0.208::dir1
Password:
@ERROR: auth failed on module dir1
rsync error: error starting client-server protocol (code 5) at main.c(1863) [Receiver=3.2.7]
#查看服务端日志,密码文件不能被所有人可读
[root@ubuntu ~]# cat /var/log/rsyncd.log
#修改密码文件权限
[root@ubuntu ~]# chmod 600 /etc/rsyncd.pwd
[root@ubuntu ~]# ll /etc/rsyncd.pwd
-rw------- 1 root root 15 Jul 13 08:58 /etc/rsyncd.pwd
#客户端再次测试
[root@ubuntu ~]# rsync /etc/hosts rsyncer@10.0.0.208::dir1
Password:
[root@ubuntu ~]# rsync rsyncer@10.0.0.208::dir1
Password:
drwxrwxr-x 4,096 2023/07/13 09:23:12 .
-rw-r--r-- 771 2023/07/12 00:02:15 fstab
-rw-r--r-- 270 2023/07/13 09:23:12 hosts
-rw-r--r-- 24 2023/07/12 00:04:37 issue
#服务端查看,新文件属主属组发生了变化
[root@ubuntu ~]# ls -lh /data/dir1/
total 12K
-rw-r--r-- 1 nobody nogroup 771 Jul 12 00:02 fstab
-rw-r--r-- 1 root root 270 Jul 13 09:23 hosts
-rw-r--r-- 1 nobody nogroup 24 Jul 12 00:04 issue
#查看客户端文件
[root@ubuntu ~]# tree /data/www/
/data/www/
├── dira
│ └── os-release
├── f1
├── f2
├── fstab
└── issue
1 directory, 5 files
#查看服务端文件
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── fstab
├── hosts
└── issue
0 directories, 3 files
#将客户端密码保存在单独文件,实现非交互式连接
[root@ubuntu ~]# echo "123456" > /etc/rsyncd.pwd
[root@ubuntu ~]# chmod 600 /etc/rsyncd.pwd
#客户端测试,保证服务端与客户端同步
#--delete 选项,此次同步完成后,删除服务端不在此次同步中的文件
#-a 保留属性
#-v 显示过程
#-z 压缩传输
[root@ubuntu ~]# rsync -avz --delete --password-file=/etc/rsyncd.pwd /data/www/ rsyncer@10.0.0.208::dir1
sending incremental file list
deleting hosts #删除了远程的 hosts 文件
./
f1
f2
fstab
issue
dira/
dira/os-release
sent 1,169 bytes received 147 bytes 2,632.00 bytes/sec total size is 1,182 speedup is 0.90
#再次查看服务端,与客户端保持一致了
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│?? └── os-release
├── f1
├── f2
├── fstab
└── issue
1 directory, 5 files
rsync 服务常用配置项
#查看配置示例
[root@ubuntu ~]# cat /usr/share/doc/rsync/examples/rsyncd.conf
# GLOBAL OPTIONS #全局配置部份
motd file=/etc/motd #motd 文件路径
log file=/var/log/rsyncd #日志文件
pid file=/var/run/rsyncd.pid #PID 文件
syslog facility=daemon #rsyslog 日志服务中的日志归类
socket options= #socket 选项,具体见 man setsockopt
[ftp] #客户端显示的名称
comment = public archive #客户端列出该共享目录时的说明信息
path = /var/www/pub #服务端具体目录
use chroot = yes #更改映射目录的根目录
max connections=10 #最大连接数,同时有多少客户端可以连接
lock file = /var/lock/rsyncd #锁文件
read only = yes #默认客户端只读访问
list = yes #客户端是否可以列出服务端内容
uid = nobody #默认将客户端上传的文件属主映射成 nobody
gid = nogroup #默认将客户端上传的文件属组映射成 nobody
exclude = #指定排除项,在此处指定的内容在客户端无法显示
exclude from = #从指定文件中读取排除项
include = #指定显示项,配合 exclude,exclude from 使用
include from = #同上
auth users = #客户端用户名,启用此项表示禁用匿名连接
secrets file = /etc/rsyncd.secrets #客户端用户名和密码对应文件
strict modes = yes #严格检查权限,此选项用于 windows 系统上的 rsync
hosts allow = #客户端白名单
hosts deny = #客户端黑名单
ignore errors = no #不忽略错误
ignore nonreadable = yes #
transfer logging = no #是否开启传输日志
log format = %t: host %h (%a) %o %f (%l bytes). Total %b bytes. #默认日志格式
timeout = 600 #超时时长
refuse options = checksum dry-run #服务端拒绝客户端执行的命令列表
dont compress = *.gz *.tgz *.zip *.z *.rpm *.deb *.iso *.bz2 *.tbz #不压缩指定文件
#查看配置帮助
[root@ubuntu ~]# man rsyncd.conf
1.2.3 inotify + rsync 实现数据实时同步
#客户端同步脚本
[root@ubuntu data]# cat ./www_rsync.sh
#!/bin/bash
SRC='/data/www/'
DEST='rsyncer@10.0.0.208::dir1'
dpkg -V inotify-tools &>/dev/null || apt install inotify-tools -y
dpkg -V rsync &>/dev/null || apt install rsync -y
#不间断监控指定目录中的特定事件,当目录中有事件发生变化时,调用 rsync 命令进行同步
inotifywait -mrq --exclude=".*\.swp" --timefmt '%Y-%m-%d %H:%M:%S' --format '%T %w %f' -e create,delete,moved_to,close_write,attrib ${SRC} | while read DATE TIME DIR FILE;do
FILEPATH=${DIR}${FILE}
rsync -az --delete --password-file=./www_rsync.pwd $SRC $DEST && echo "At ${TIME} on ${DATE}, file ${FILEPATH} was backup via rsync" >> ./www_rsync.log
done
#查看客户端
[root@ubuntu ~]# tree /data/
/data/
├── www
├── www_rsync.pwd
└── www_rsync.sh
1 directory, 2 files
#测试,客户端运行脚本
[root@ubuntu data]# ./www_rsync.sh
#在另一个终端中创建文件
[root@ubuntu ~]# touch /data/www/f1
[root@ubuntu ~]# cp /etc/fstab /data/www/
[root@ubuntu ~]# dd if=/dev/zero of=/data/www/test.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00923138 s, 1.1 GB/s
[root@ubuntu ~]# mkdir -pv /data/www/dira/dirb/dirc
mkdir: created directory '/data/www/dira'
mkdir: created directory '/data/www/dira/dirb'
mkdir: created directory '/data/www/dira/dirb/dirc'
#在服务湍查看
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│ └── dirb
│ └── dirc
├── f1
├── fstab
└── test.img
3 directories, 3 files
#查看客户端日志,由于某些行为会触发多个事件,导致多次调用脚本,效率不高
[root@ubuntu ~]# cat /data/www_rsync.log
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:14:53 on 2025-01-13, file /data/www/f1 was backup via rsync
At 03:15:05 on 2025-01-13, file /data/www/fstab was backup via rsync
At 03:15:05 on 2025-01-13, file /data/www/fstab was backup via rsync
At 03:15:45 on 2025-01-13, file /data/www/test.img was backup via rsync
At 03:15:45 on 2025-01-13, file /data/www/test.img was backup via rsync
At 03:16:05 on 2025-01-13, file /data/www/dira was backup via rsync
1.3 sersync 实现数据实时同步
sersync 类似 于inotify,同样用于监控,但它克服了 inotify 的缺点,inotify 最大的不足是会产生重复事件,或者同一个目录下多个文件的操作会产生多个事件,例如,当监控目录中有5个文件时,删除目录时会产生6个监控事件,从而导致重复调用 rsync 命令。另外比如:vim 文件时,inotify 会监控到临时文件的事件,但这些事件相对于 rsync 来说是不应该被监控的。
sersync 特点
-
sersync是使用c++编写,而且对linux系统文件系统产生的临时文件和重复的文件操作进行过滤,所以在结合rsync同步的时候,节省了运行时耗和网络资源。因此更快。
-
sersync 配置很简单,其中提供了静态编译好的二进制文件和 xml 配置文件,直接使用即可
-
sersync 使用多线程进行同步,尤其在同步较大文件时,能够保证多个服务器实时保持同步状态
-
sersync 有出错处理机制,通过失败队列对出错的文件重新同步,如果仍旧失败,则按设定时长对同步失败的文件重新同步
-
sersync 不仅可以实现实时同步,另外还自带 crontab 功能,只需在 xml 配置文件中开启,即也可以 按要求隔一段时间整体同步一次,而无需再额外配置 crontab 功能
-
sersync 可以二次开发
https://code.google.com/archive/p/sersync/ #项目地址
#下载
[root@ubuntu ~]# wget https://storage.googleapis.com/google-code-archive-downloads/v2/code.google.com/sersync/sersync2.5.4_64bit_binary_stable_final.tar.gz
#解压
[root@ubuntu ~]# tar xf sersync2.5.4_64bit_binary_stable_final.tar.gz
[root@ubuntu ~]# ls
GNU-Linux-x86 sersync2.5.4_64bit_binary_stable_final.tar.gz snap
[root@ubuntu ~]# ls GNU-Linux-x86/
confxml.xml sersync2
#移动
[root@ubuntu ~]# mv GNU-Linux-x86/ /usr/local/sersync
[root@ubuntu ~]# ls /usr/local/sersync/
confxml.xml sersync2
配置文件说明
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="localhost" port="8008"></host>
<debug start="false"/> #是否开启调试模式
<fileSystem xfs="false"/>
<filter start="false"> #不开启文件过滤功能,当为true时,下列文件不同步
<exclude expression="(.*)\.svn"></exclude>
<exclude expression="(.*)\.gz"></exclude>
<exclude expression="^info/*"></exclude>
<exclude expression="^static/*"></exclude>
</filter>
<inotify> #具体监控的事件
<delete start="true"/>
<createFolder start="true"/>
<createFile start="false"/>
<closeWrite start="true"/>
<moveFrom start="true"/>
<moveTo start="true"/>
<attrib start="false"/> #此处改为true,则文件属性发生变化,也会同步
<modify start="false"/>
</inotify>
<sersync> #rsync命令的配置段
<localpath watch="/opt/tongbu"> #需要同步的目录
<remote ip="127.0.0.1" name="tongbu1"/> #远程主机地址和目录
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<rsync>
<commonParams params="-artuz"/> #指定rsync选项
<auth start="false" users="root" passwordfile="/etc/rsync.pas"/>#修改为true,指定rsync用户名和密码文件
<userDefinedPort start="false" port="874"/> #指定非标准端口
<!-- port=874 -->
<timeout start="false" time="100"/>
<!-- timeout=100 -->
<ssh start="false"/> #默认远程rsync daemon运行,true为使用远程shell
</rsync>
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/>#错误重传及日志文件路径
<!--default every 60mins execute once-->
<crontab start="false" schedule="600"><!--600mins-->#不开启crontab功能
<crontabfilter start="false"> #不开启crontab定时传输的筛选功能
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
<plugin start="false" name="command"/>
</sersync>
#以下不需要修改
<plugin name="command">
<param prefix="/bin/sh" suffix="" ignoreError="true"/> <!--prefix /opt/tongbu/mmm.sh suffix-->
<filter start="false">
<include expression="(.*)\.php"/>
<include expression="(.*)\.sh"/>
</filter>
</plugin>
<plugin name="socket">
<localpath watch="/opt/tongbu">
<deshost ip="192.168.138.20" port="8009"/>
</localpath>
</plugin>
<plugin name="refreshCDN">
<localpath watch="/data0/htdocs/cms.xoyo.com/site/">
<cdninfo domainname="ccms.chinacache.com" port="80" username="xxxx" passwd="xxxx"/>
<sendurl base="http://pic.xoyo.com/cms"/>
<regexurl regex="false" match="cms.xoyo.com/site([/a-zA-Z0-9]*).xoyo.com/images"/>
</localpath>
</plugin>
</head>
sersync2 命令用法和参数
[root@ubuntu sersync]# ./sersync2 -h
set the system param
execute:echo 50000000 > /proc/sys/fs/inotify/max_user_watches
execute:echo 327679 > /proc/sys/fs/inotify/max_queued_events
parse the command param
_______________________________________________________
参数-d:启用守护进程模式
参数-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
参数-n:指定开启守护线程的数量,默认为10个
参数-o:指定配置文件,默认使用confxml.xml文件
参数-m:单独启用其他模块,使用 -m refreshCDN 开启刷新CDN模块
参数-m:单独启用其他模块,使用 -m socket 开启socket模块
参数-m:单独启用其他模块,使用 -m http 开启http模块
不加-m参数,则默认执行同步程序
_________________________________________________
客户端测试
#服务端文件
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
└── f2
0 directories, 1 file
#客户端文件
[root@ubuntu ~]# tree /data/www
/data/www
└── f1
0 directories, 1 file
[root@ubuntu ~]# cd /usr/local/sersync/
[root@ubuntu sersync]# ./sersync2 -dro ./confxml.xml
#查看服务端,己经和客户端保持一致了
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
└── f1
0 directories, 1 file
#客户端测试
[root@ubuntu ~]# mkdir -pv /data/www/dira/dirb/dirc
mkdir: created directory '/data/www/dira'
mkdir: created directory '/data/www/dira/dirb'
mkdir: created directory '/data/www/dira/dirb/dirc'
[root@ubuntu ~]# cp /etc/fstab /data/www/
[root@ubuntu ~]# dd if=/dev/zero of=/data/www/test.img bs=1M count=10
10+0 records in
10+0 records out
10485760 bytes (10 MB, 10 MiB) copied, 0.00870068 s, 1.2 GB/s
#服务端查看
[root@ubuntu ~]# tree /data/dir1/
/data/dir1/
├── dira
│ └── dirb
│ └── dirc
├── f1
├── fstab
└── test.img
3 directories, 3 files
#客户端查看后台进程
[root@ubuntu ~]# ps aux | grep rsync
root 5249 0.0 0.0 116928 1624 ? Ssl 07:02 0:00 ./sersync2 -dro ./confxml.xml
root 5307 0.0 0.1 6476 2324 pts/0 S+ 07:04 0:00 grep --color=auto rsync