实时同步
一、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安装使用
# 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使用
# 打开两个窗口,一个窗口执行命令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 事件:CREATE1.3 编写监控脚本
编写脚本前提:需要在服务端中提前搭建好rsync服务端,配置好相应的配置文件
以下为监控脚本:
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 1fi
if [ ! -f "$RSYNC_PASSWORD_FILE" ]; then echo "错误: 密码文件不存在: $RSYNC_PASSWORD_FILE" echo "请创建该文件并写入密码,然后执行: chmod 600 $RSYNC_PASSWORD_FILE" exit 1fi
if [ ! -d "$LOCAL_DIR" ]; then echo "错误: 本地目录不存在: $LOCAL_DIR" exit 1fi
# 确保路径以 / 结尾[[ "$LOCAL_DIR" != */ ]] && LOCAL_DIR="$LOCAL_DIR/"
# myuser@10.1.1.29::backupREMOTE_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::backupif rsync $RSYNC_OPTS "$LOCAL_DIR" "$REMOTE_TARGET"; then echo "初始同步完成"else echo "初始同步失败,请检查网络、权限或 rsync 服务配置" exit 1fi
# 开始实时监控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 服务状态或认证信息" fidone1.3.1 修改文件权限,修改脚本后台运行
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 测试
# 在nfs的/etc/nginx文件夹中创建文件,查看是否同步过去touch nihao.txt# 删除文件rm -rf nihao.txt# 查看日志vim /etc/rsync-iontify.log# 查看rsync服务端是否接收到了文件cd /backup1.3.3 创建systemd服务文件,实现脚本开机自启(可选)
vim /etc/systemd/system/inotify-rsync.service[Unit]Description=Inotify + Rsync Realtime SyncRequires=rsyncd.serviceAfter=rsyncd.service network.target
[Service]Type=simpleUser=rootExecStart=/bin/bash /etc/rsync-inotify.shRestart=alwaysRestartSec=5
[Install]WantedBy=multi-user.target自启动服务
systemctl daemon-reloadsystemctl enable --now inotify-rsync.service1.4 修改inotify默认参数(可选)
inotify默认内核参数值太小,分别就是 查看系统默认参数值
sysctl -a | grep max_queued_events结果是:fs.inotify.max_queued_events = 16384sysctl -a | grep max_user_watches结果是:fs.inotify.max_user_watches = 8192sysctl -a | grep max_user_instances结果是:fs.inotify.max_user_instances = 128修改参数命令
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文件添加以下内容
vim /etc/sysctl.conf
fs.inotify.max_queued_events=99999999fs.inotify.max_user_watches=99999999fs.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安装
cd /usr/localwget 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 sersynccp confxml.xml confxml.xml-bak #备份原文件vim confxml.xml #编辑,修改下面的代码2.1 修改serync区块内容
<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守护进程同步数据并测试程序
/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服务器是否同步过来
cd /backupls# 在nfs客户端的/nfs-nginx/创建文件touch hello.txt# 再次查看是否同步过来,删除后呢2.3 配置sersync环境变量并开机启动
配置环境变量
echo"PATH=$PATH:/usr/local/sersync/">>/etc/profilesource /etc/profile将命令添加到/etc/rc.local,实现开机启动:
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 安装配置
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 常用配置
# 示例配置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 启动测试
systemctl start lsyncd
# 查看rsync服务端是否接收到了文件
cd /backupll文章分享
如果这篇文章对你有帮助,欢迎分享给更多人!
赣公网安备36072602000131号