实时同步

3392 字
17 分钟
实时同步

一、inotify+rsync实现实时同步#

1.1 环境准备#

测试环境介绍:2台机器,系统Linux(centos 7) nfs存储共享服务器ip:10.1.1.28 (已安装nfs,rsync) rsync备份服务器ip :10.1.1.29(已安装rsync服务端) 实现效果:inotify+rsync监控nfs服务器 /nfs-nginx目录,有更新或修改文件后,同步至rsync备份服务器/backup/目录。

1.2 inotify-tools安装使用#

Terminal window
# nfs服务器安装inotify-tools工具
yum install inotify-tools -y
# 使用语法格式
inotifywait [选项] 文件或目录...
# 选项参数
-r:递归查询目录
-q:打印监控时间信息
-m:始终保持时间监听状态
--excludei: 排除文件或目录时,不区分大小写。
--timefmt: 指定时间输出的格式
--format: 打印使用指定的输出类似格式字符串
# 自定义输出格式参数
a、 %w:显示被监控文件的文件名;
b、 %f:如果发生某事件的对象是目录,则显示被监控目录的名字;默认显示为空串;
c、 %T:使用--timefmt 选项中自定义的时间格式;
d、 %e 表示发生的事件
e、 %Xe 事件以“X”分隔
# -e:指定需要监控的事件
access: 文件或目录被读取
modify: 文件或目录内容被修改
attrib: 文件或目录属性被改变
close: 文件或目录封闭,无论读/写模式
open:文件或目录被打开
move_to:文件或目录被移动到另外一个目录
move:文件或目录被移动另一个目录或从另一个目录移动到当前目录
create:文件或目录被创建在当前目录
delete:文件或目录被删除
unmount:文件系统被卸载
常用组合:close_write,modify,delete,create,attrib

测试inotify使用

Terminal window
# 打开两个窗口,一个窗口执行命令
inotifywait -mrq --timefmt '%Y-%m-%d %H:%M' --format '%T %w %f 事件:%e' -e create delete modify /nfs-nginx
# 另一个窗口在监控目录下创建文件
touch hello.txt
# 看到如下信息表示监控成功
2026-01-15 11:51 /nfs-nginx/ hello.txt 事件:CREATE

1.3 编写监控脚本#

编写脚本前提:需要在服务端中提前搭建好rsync服务端,配置好相应的配置文件

以下为监控脚本:

Terminal window
vim /etc/rsync-inotify.sh
#!/bin/bash
# ================== 配置区 ==================
LOCAL_DIR="/nfs-nginx" # 本地监控目录(绝对路径)
RSYNC_MODULE="backup" # rsyncd.conf 中定义的模块名
RSYNC_USER="myuser" # rsync 用户名(auth users 中定义)
RSYNC_HOST="10.1.1.29" # rsync 服务器 IP 或域名
RSYNC_PASSWORD_FILE="/etc/rsync.passwd" # 密码文件路径(chmod 600)
# srsync 备份参数
RSYNC_OPTS="-avz --delete --password-file=$RSYNC_PASSWORD_FILE"
# inotify 事件参数
INOTIFY_EVENTS="create,modify,delete,move,attrib"
# ===========================================
# 检查依赖
if ! command -v inotifywait &> /dev/null; then
echo "错误: inotifywait 未安装,请先安装 inotify-tools"
exit 1
fi
if [ ! -f "$RSYNC_PASSWORD_FILE" ]; then
echo "错误: 密码文件不存在: $RSYNC_PASSWORD_FILE"
echo "请创建该文件并写入密码,然后执行: chmod 600 $RSYNC_PASSWORD_FILE"
exit 1
fi
if [ ! -d "$LOCAL_DIR" ]; then
echo "错误: 本地目录不存在: $LOCAL_DIR"
exit 1
fi
# 确保路径以 / 结尾
[[ "$LOCAL_DIR" != */ ]] && LOCAL_DIR="$LOCAL_DIR/"
# myuser@10.1.1.29::backup
REMOTE_TARGET="${RSYNC_USER}@${RSYNC_HOST}::${RSYNC_MODULE}"
echo "监控目录: $LOCAL_DIR"
echo "同步目标: $REMOTE_TARGET"
echo "按 Ctrl+C 停止..."
# 初始全量同步
echo "执行初始同步..."
# rsync -avz --delete --password-file=/etc/rsync.passwd /nfs-nginx myuser@10.1.1.29::backup
if rsync $RSYNC_OPTS "$LOCAL_DIR" "$REMOTE_TARGET"; then
echo "初始同步完成"
else
echo "初始同步失败,请检查网络、权限或 rsync 服务配置"
exit 1
fi
# 开始实时监控
echo "开始监听文件系统事件..."
inotifywait -m -r -e $INOTIFY_EVENTS --timefmt '%Y-%m-%d %H:%M' --format '%T %w %f 事件:%e' "$LOCAL_DIR" | while read filepath event; do
echo "$(date '+%Y-%m-%d %H:%M:%S') 检测到变更: $filepath ($event)"
# 执行增量同步(整个目录,由 rsync 处理差异)
if rsync $RSYNC_OPTS "$LOCAL_DIR" "$REMOTE_TARGET"; then
echo "同步成功"
else
echo "同步失败!请检查 rsync 服务状态或认证信息"
fi
done

1.3.1 修改文件权限,修改脚本后台运行#

Terminal window
chmod 755 /etc/rsync-inotify.sh
# 后台运行,并写入日志
nohup /etc/rsync-inotify.sh > /etc/rsync-inotify.log 2>&1 &
# 查看日志信息
tail -f rsync-inotify.log
# 查看进程
ps -ef | grep "rsync-inotify.sh"
# 结束运行
kill 进程号

1.3.2 测试#

Terminal window
# 在nfs的/etc/nginx文件夹中创建文件,查看是否同步过去
touch nihao.txt
# 删除文件
rm -rf nihao.txt
# 查看日志
vim /etc/rsync-iontify.log
# 查看rsync服务端是否接收到了文件
cd /backup

1.3.3 创建systemd服务文件,实现脚本开机自启(可选)#

/etc/systemd/system/inotify-rsync.service
vim /etc/systemd/system/inotify-rsync.service
[Unit]
Description=Inotify + Rsync Realtime Sync
Requires=rsyncd.service
After=rsyncd.service network.target
[Service]
Type=simple
User=root
ExecStart=/bin/bash /etc/rsync-inotify.sh
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target

自启动服务

Terminal window
systemctl daemon-reload
systemctl enable --now inotify-rsync.service

1.4 修改inotify默认参数(可选)#

inotify默认内核参数值太小,分别就是 查看系统默认参数值

Terminal window
sysctl -a | grep max_queued_events
结果是:fs.inotify.max_queued_events = 16384
sysctl -a | grep max_user_watches
结果是:fs.inotify.max_user_watches = 8192
sysctl -a | grep max_user_instances
结果是:fs.inotify.max_user_instances = 128

修改参数命令

Terminal window
sysctl -w fs.inotify.max_queued_events="99999999"
sysctl -w fs.inotify.max_user_watches="99999999"
sysctl -w fs.inotify.max_user_instances="65535"

并在sysctl.conf文件添加以下内容

Terminal window
vim /etc/sysctl.conf
fs.inotify.max_queued_events=99999999
fs.inotify.max_user_watches=99999999
fs.inotify.max_user_instances=65535

保存退出完成。

参数说明: max_queued_events: inotify队列最大长度,如果值太小,会出现”** Event Queue Overflow **“错误,导致监控文件不准确

max_user_watches: 设置inotifywait或inotifywatch命令可以监视的文件数量(单进程)

max_user_instances: 每个用户创建inotify实例最大值 【inotify在实际生产环境中,对于50-200KB的文件,inotify的最发并发量为200-300,如果客户端写入速度大于这个量,将会造成短暂的延迟】

二、sersync+rsync实现实时同步#

2.1 sersync简介#

sersync是基于inotify开发的,类似于inotify-tools的工具。所以同样内核需先支持inotify,才能搭建。

sersync可以记录下被监听目录中发生变化的(包括增加、删除、修改)具体某一个文件或者某一个目录的名字,然后使用rsync同步的时候,只同步发生变化的文件或者目录。

相对于inotify-tools遍历更快,在同步大量数据时更有优势,搭建更快,无需额外编写脚本。

2.2 sersync安装#

Terminal window
cd /usr/local
wget https://github.com/wsgzao/sersync/raw/refs/heads/master/sersync2.5.4_64bit_binary_stable_final.tar.gz
# 解压
tar -xvf sersync2.5.4_64bit_binary_stable_final.tar.gz
# 修改名字
mv ./GNU-Linux-x86/ sersync
cd sersync
cp confxml.xml confxml.xml-bak #备份原文件
vim confxml.xml #编辑,修改下面的代码

2.1 修改serync区块内容#

Terminal window
<sersync>
# 这里填写nfs存储服务器(源服务器)要同步的文件夹路径。
<localpath watch="/nfs-nginx">
# 填写对端ip,即rsync的ip及模块名,可配置多个对端服务器
<remote ip="10.1.1.29" name="backup"/>
<!--<remote ip="192.168.8.39" name="tongbu"/>-->
<!--<remote ip="192.168.8.40" name="tongbu"/>-->
</localpath>
<rsync>
# 此为rsync的选项参数
<commonParams params="-avz --delete"/>
#启用密码认证,配置auth users+密码文件路径,rsync备份服务器的认证信息。
<auth start="true" users="myuser" passwordfile="/etc/rsync.passwd"/>
# 指定 rsync 服务的自定义端口,通常不修改
<userDefinedPort start="false" port="874"/><!-- port=874 -->
# 设置 rsync 命令的超时时间(秒)
<timeout start="false" time="100"/><!-- timeout=100 -->
# 是否使用 SSH 模式,否为daemon模式
<ssh start="false"/>
</rsync>
# 当同步失败时,sersync 会将失败的 rsync 命令写入 path 指定的脚本文件 默认60分钟执行一次脚本
<failLog path="/tmp/rsync_fail_log.sh" timeToExecute="60"/><!--default every 60mins execute once-->
# 定期全量同步,默认600分钟
<crontab start="false" schedule="600"><!--600mins-->
# 同步时文件过滤
<crontabfilter start="false">
<exclude expression="*.php"></exclude>
<exclude expression="info/*"></exclude>
</crontabfilter>
</crontab>
#启用插件机制(如同步后执行自定义命令)
#name="command":表示使用命令插件(可在文件变动后触发 shell 命令)
<plugin start="false" name="command"/>
</sersync>

2.2 开启sersync守护进程同步数据并测试程序#

Terminal window
/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml
参数用法:
-d:启用守护进程模式
-r:在监控前,将监控目录与远程主机用rsync命令推送一遍
-n: 指定开启守护线程的数量,默认为10个
-o:指定配置文件,默认使用confxml.xml文件
# 查看守护进程是否开启
[root@nfs-28 /usr/local/sersync]#ps -ef | grep "sersync"
root 21495 1 0 16:17 ? 00:00:00 /usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml

查看rsync服务器是否同步过来

Terminal window
cd /backup
ls
# 在nfs客户端的/nfs-nginx/创建文件
touch hello.txt
# 再次查看是否同步过来,删除后呢

2.3 配置sersync环境变量并开机启动#

配置环境变量

Terminal window
echo"PATH=$PATH:/usr/local/sersync/">>/etc/profile
source /etc/profile

将命令添加到/etc/rc.local,实现开机启动:

Terminal window
echo '/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/conf/confxml.xml' >> /etc/rc.local

三、lsyncd实现实时同步#

3.1 lsyncd简介#

Lysncd 实际上是lua语言封装了 inotify 和 rsync 工具,采用了 Linux 内核(2.6.13 及以后)里的 inotify 触发机制,然后通过rsync去差异同步,达到实时的效果。我认为它最令人称道的特性是,完美解决了 inotify + rsync海量文件同步带来的文件频繁发送文件列表的问题:通过时间延迟或累计触发事件次数实现。另外,它的配置方式很简单,lua本身就是一种配置语言,可读性非常强。lsyncd也有多种工作模式可以选择,本地目录cp,本地目录rsync,远程目录rsyncssh。 实现简单高效的本地目录同步备份(网络存储挂载也当作本地目录),一个命令搞定。

3.2 安装配置#

Terminal window
yum install lsyncd -y
# 配置文件路径
vim /etc/lsyncd.conf
# 文件参数说明
# -- 全局配置:
settings {
logfile ="/var/log/lsyncd/lsyncd.log", # -- 定义日志文件
statusFile ="/var/log/lsyncd/lsyncd.status", # -- 定义状态文件
pidfile = "/var/log/lsyncd/lsyncd.pid",# -- 定义pid文件
inotifyMode = "CloseWrite",# -- 指定inotify监控的事件,默认是CloseWrite,还可以是Modify或CloseWrite or Modify
maxProcesses = 7,# -- 同步进程的最大个数。假如同时有20个文件需要同步,而maxProcesses = 8,则最大能看到有8个rysnc进程
nodaemon =true,# -- 表示不启用守护模式,默认;
maxDelays = 1, # -- 累计到多少所监控的事件激活一次同步,即使后面的delay延迟时间还未到
inist = ture # --keep running at startup although one or more targets failed due to not being reachable. 一般不用配置
}
# -- sync部分配置:
sync {
default.rsync, # -- rsync、rsyncssh、direct三种模式:
# -- default.rsync :本地目录间同步,使用rsync,也可以达到使用ssh形式的远程rsync效果,或daemon方式连接远程rsyncd进程;
# -- default.direct :本地目录间同步,使用cp、rm等命令完成差异文件备份;
# -- default.rsyncssh :同步到远程主机目录,rsync的ssh模式,需要使用key来认证;
source = "/tmp/src", # -- source 同步的源目录,使用绝对路径
target = "/tmp/dest", # -- target 定义目的地址.对应不同的模式有几种写法:
# -- /tmp/dest :本地目录同步,可用于direct和rsync模式;
# -- 10.4.7.10:/tmp/dest :同步到远程服务器目录,可用于rsync和rsyncssh模式,拼接的命令类似于/usr/bin/rsync -ltsd --delete --include-from=- --exclude=* SOURCE TARGET,剩下的就是rsync的内容了,比如指定username,免密码同步;
# -- 10.4.7.10::module :同步到远程服务器目录,用于rsync模式;
init = true, # -- init 这是一个优化选项,当init = false,只同步进程启动以后发生改动事件的文件,原有的目录即使有差异也不会同步。默认是true;
delay = 3, # -- delay 累计事件,等待rsync同步延时时间,默认15秒(最大累计到1000个不可合并的事件)。也就是15s内监控目录下发生的改动,会累积到一次rsync同步,避免过于频繁的同步。(可合并的意思是,15s内两次修改了同一文件,最后只同步最新的文件);
excludeFrom = "/etc/rsyncd.d/rsync_exclude.lst", # -- excludeFrom 排除选项,后面指定排除的列表文件,如excludeFrom = "/etc/lsyncd.exclude",如果是简单的排除,可以使用exclude = LIST。这里的排除规则写法与原生rsync有点不同,更为简单:
# -- 监控路径里的任何部分匹配到一个文本,都会被排除,例如/bin/foo/bar可以匹配规则foo
# -- 如果规则以斜线/开头,则从头开始要匹配全部
# -- 如果规则以/结尾,则要匹配监控路径的末尾
# -- ?匹配任何字符,但不包括/
# -- *匹配0或多个字符,但不包括/
# -- **匹配0或多个字符,可以是/
delete = 'running', # -- delete 为了保持target与souce完全同步,Lsyncd默认会delete = true来允许同步删除。它除了false,还有startup、running值:
-- delete = true # 始终删除:无论启动时还是运行中,都会删除目标上源没有的文件
-- delete = false # 从不删除:不会删除目标上的任何文件,即使源删了
-- delete = 'startup' # 仅启动时删除:开机或重启 lsyncd 时清理目标多余文件,但运行中不删
-- delete = 'running' # 仅运行时删除:启动时不删,但运行中会删除源已删的文件
# -- rsync部分配置:
# -- delete和exclude本来都是rsync的选项,上面是配置在sync中的,这样做的原因是为了减少rsync的开销
rsync = {
bwlimit=200, # -- bwlimit 限速,单位kb/s,与rsync相同(这么重要的选项在文档里竟然没有标出);
binary = "/usr/bin/rsync", # -- rsync可执行程序地址,默认/usr/bin/rsync
archive = true, # -- 默认false,以递归方式传输文件,并保持所有文件属性
compress = true,# -- 压缩传输默认为true。在带宽与cpu负载之间权衡,本地目录同步可以考虑把它设为false;
verbose = true,# --同步详细模式输出
perms = true # -- perms 保留文件权限,默认为true;
_extra = { # --rsyn附加参数
"--delete",
"--password-file=/etc/rsync.passwd"
}
}
}

lsyncd同样支持多个文件夹同步,创建多个sync{ }块即可实现

3.2.1 常用配置#

Terminal window
# 示例配置
sync {
default.rsync,
source = "/nfs-nginx/",
target = "mysuer@10.1.1.29::backup",
delay = 5,
delete = true,
rsync = {
binary = "/usr/bin/rsync",
archive = true,
compress = true,
verbose = true,
perms = true,
_extra = {
"--delete",
"--password-file=/etc/rsync.passwd"
}
}
}

3.3 启动测试#

Terminal window
systemctl start lsyncd
# 查看rsync服务端是否接收到了文件
cd /backup
ll

文章分享

如果这篇文章对你有帮助,欢迎分享给更多人!

实时同步
https://2233941.xyz/posts/实时同步/
作者
lumifly
发布于
2026-04-05
许可协议
CC BY-NC-SA 4.0
Profile Image of the Author
lumifly
不逐世间万丈星河,自守一隅细碎明光
✨ 今日一言
" 加载中... "
——
公告
欢迎来到我的博客!这是一则示例公告。
音乐
封面

音乐

暂未播放

0:00 0:00
暂无歌词
分类
标签
本年还剩 -- --%
本月还剩 -- --%
本周还剩 -- --%
距离--
--
--
天气预报
站点统计
文章
7
分类
1
标签
3
总字数
38,070
运行时长
0
最后活动
0 天前
站点信息
构建平台
Local
博客版本
Firefly v6.12.1
文章许可
CC BY-NC-SA 4.0

文章目录