使用inotify + rsync和sersync实现文件的同步,并且总结两种方式的优缺点
一、核心原理
1. inotify 原理
inotify 是Linux内核(2.6.13+)内置的文件系统事件监控接口,以「事件驱动」替代传统定时轮询:
- 核心能力:实时捕获目录/文件的创建、删除、修改、移动、属性变更等事件,响应延迟仅毫秒级;
- 资源占用:仅监控目标目录,无事件时CPU/内存占用趋近于0;
- 核心工具:
inotifywait(持续监控并输出触发事件的文件路径)、inotifywatch(统计事件频次,用于调试)。
2. rsync 原理
rsync 是Linux工业级增量同步工具,解决"全量拷贝耗带宽/资源"的问题:
- 同步逻辑:首次同步全量拷贝文件,后续仅传输「文件差异部分」(通过MD5校验+分块对比);
- 核心特性:
- 免密同步:适配SSH免密,无需手动输入密码;
- 压缩传输:-z参数压缩数据,降低网络带宽占用;
- 一致性保障:--delete参数删除目标主机冗余文件,保持源/目标目录完全一致;
- 属性保留:-a参数保留文件权限、时间戳、属主等属性。
3. sersync 原理
sersync 是基于 inotify+rsync 的二次开发工具,解决原生方案的核心痛点:
- 原生痛点:短时间内高频修改同一文件(如1秒改3次),会触发3次rsync调用,浪费系统资源;
- 核心优化:内置「事件队列」,合并5秒内的重复事件(如1秒改3次仅触发1次rsync);
- 额外优势:
- 配置化管理:通过XML文件整合监控规则、同步参数,无需编写shell脚本;
- 多目标同步:支持同时同步到多台服务器;
- 日志轮转:自动切割日志,避免日志文件过大。
二、环境说明
| 主机角色 |
IP地址 |
核心操作 |
依赖工具 |
| 源主机 |
10.0.0.12 |
部署监控同步服务、触发同步 |
inotify-tools/rsync/sersync |
| 目标主机 |
10.0.0.15 |
接收同步数据 |
rsync(仅需接收能力) |
三、详细安装步骤
1. 源主机安装核心依赖
bash
复制代码
# 命令1:安装EPEL第三方源(Rocky 9官方源无inotify-tools,必须先装)
yum install -y epel-release
# 作用:启用EPEL仓库(包含inotify-tools等第三方工具)
# 预期结果:提示"已安装"或"完毕",无报错
# 命令2:安装同步核心工具
yum install -y inotify-tools rsync wget tar
# 作用:
# - inotify-tools:提供inotifywait监控工具(inotify+rsync方案核心);
# - rsync:实现增量同步(所有方案均依赖);
# - wget/tar:下载解压sersync安装包(sersync方案需用);
# 验证安装:执行 inotifywait --help | head -1,输出版本号即成功
2. 目标主机基础配置
bash
复制代码
# 命令:创建同步目录+安装rsync(仅需接收同步数据)
mkdir -p /data/sync_dir && chmod 755 /data/sync_dir && yum install -y rsync
# 作用:
# - mkdir -p:递归创建目录,避免"目录不存在"报错;
# - chmod 755:保证root可读写,其他用户可读取,避免权限不足;
# - yum install rsync:安装接收同步的工具,无rsync则无法接收数据;
# 验证:ls -ld /data/sync_dir,输出 drwxr-xr-x 2 root root ... 即正常
四、方案1:inotify+rsync
1. 源主机配置SSH免密
bash
复制代码
# 命令:生成免密密钥对+推送公钥到目标主机
ssh-keygen -t rsa -b 2048 -N '' && ssh-copy-id root@10.0.0.15
# 逐段解释:
# - ssh-keygen -t rsa -b 2048 -N '':生成无密码的RSA密钥对(-N ''=空密码);
# - ssh-copy-id root@10.0.0.15:将公钥推送到目标主机,授权免密登录;
# 执行提示:输入目标主机root密码(仅首次需要);
# 验证免密:ssh root@10.0.0.15 "echo 免密成功",无密码提示且输出"免密成功"即生效
2. 源主机创建同步脚本
bash
复制代码
cat > /usr/local/bin/inotify_sync.sh << 'EOF'
#!/bin/bash
# ===================== 核心配置(可按需修改) =====================
SRC_DIR="/data/sync_dir" # 源主机同步目录
DEST_HOST="10.0.0.15" # 目标主机IP
DEST_USER="root" # 目标主机登录用户(与免密配置一致)
DEST_DIR="/data/sync_dir" # 目标主机同步目录(需与源主机一致)
LOG_FILE="/var/log/inotify_sync.log" # 同步日志(排查问题核心)
EVENT_TYPES="create,delete,modify,move" # 监控的事件类型
SLEEP_TIME=0.5 # 事件合并时间(0.5秒内重复事件仅触发1次同步)
# ===================== 初始化操作(避免运行报错) =====================
# 确保同步目录存在
mkdir -p ${SRC_DIR}
# 确保日志文件存在,避免写入失败
touch ${LOG_FILE}
# 给日志文件赋权,避免权限不足
chmod 644 ${LOG_FILE}
# ===================== 核心监控+同步逻辑 =====================
# 持续监控目录事件
inotifywait -mrq -e ${EVENT_TYPES} ${SRC_DIR} | while read FILE_PATH FILE_EVENT FILE_NAME
do
# 合并短时间内的重复事件,降低rsync调用次数
sleep ${SLEEP_TIME}
# 执行增量同步(核心命令)
rsync -avz --delete \
${SRC_DIR}/ \
${DEST_USER}@${DEST_HOST}:${DEST_DIR}/ \
>> ${LOG_FILE} 2>&1
# 记录同步日志(便于排查问题)
echo "[$(date +'%Y-%m-%d %H:%M:%S')] 事件:${FILE_EVENT} | 同步文件:${FILE_NAME} | 状态:完成" >> ${LOG_FILE}
done
EOF
3. 源主机启动&持久化服务
bash
复制代码
# 步骤1:给脚本添加执行权限(Linux脚本必须有x权限才能运行)
chmod +x /usr/local/bin/inotify_sync.sh
# 步骤2:创建systemd服务文件(实现开机自启+崩溃自动重启)
cat > /usr/lib/systemd/system/inotify-sync.service << 'EOF'
[Unit]
Description=Inotify+Rsync Real-Time Sync Service
After=network.target sshd.service
# 网络、SSH启动后再启动本服务,避免依赖问题
Documentation=man:inotifywait(1) man:rsync(1)
[Service]
Type=simple
# 简单服务类型(脚本持续运行,无复杂fork)
ExecStart=/usr/local/bin/inotify_sync.sh
# 脚本绝对路径(必须准确)
Restart=always
# 脚本崩溃/被杀死时,自动重启(核心保障)
RestartSec=3
# 重启间隔3秒,避免频繁重启耗资源
User=root
# 以root运行,保证目录读写权限
StandardOutput=append:/var/log/inotify_sync.log
# 标准输出重定向到日志
StandardError=append:/var/log/inotify_sync.log
# 错误输出重定向到日志
[Install]
WantedBy=multi-user.target
# 多用户模式下开机自启(服务器默认模式)
EOF
# 步骤3:启动服务并设置开机自启
systemctl daemon-reload # 重新加载systemd配置,识别新服务
systemctl start inotify-sync # 启动同步服务
systemctl enable inotify-sync # 设置开机自启
systemctl status inotify-sync # 验证服务状态
# 状态验证标准:
# 1. 服务行显示 active (running)(绿色);
# 2. 无 red 报错信息;
# 3. 进程行能看到 inotify_sync.sh 进程。
4. 详细验证同步
bash
复制代码
# 场景1:创建文件同步
# 源主机执行
touch /data/sync_dir/test_create.txt && echo "创建文件测试" > /data/sync_dir/test_create.txt
# 目标主机验证(预期:文件存在+内容一致)
ssh root@10.0.0.15 "cat /data/sync_dir/test_create.txt"
# 场景2:修改文件同步
# 源主机执行
echo "新增修改内容" >> /data/sync_dir/test_create.txt
# 目标主机验证(预期:内容包含新增行)
ssh root@10.0.0.15 "cat /data/sync_dir/test_create.txt"
# 场景3:删除文件同步
# 源主机执行
rm -f /data/sync_dir/test_create.txt
# 目标主机验证(预期:文件不存在)
ssh root@10.0.0.15 "ls /data/sync_dir/test_create.txt"
# 场景4:目录+嵌套文件同步
# 源主机执行
mkdir -p /data/sync_dir/test_dir/sub_dir && touch /data/sync_dir/test_dir/sub_dir/nested.txt
# 目标主机验证(预期:目录和文件均存在)
ssh root@10.0.0.15 "ls /data/sync_dir/test_dir/sub_dir/nested.txt"
# 场景5:查看同步日志(验证事件记录)
# 源主机执行
tail -n 10 /var/log/inotify_sync.log
# 预期:日志包含上述所有操作的时间、事件类型、文件名,无 error 关键词。
五、方案2:sersync
1. 源主机安装sersync
bash
复制代码
# 步骤1:下载sersync预编译包(64位,兼容Rocky 9)
yum install -y wget
wget https://github.com/wsgzao/sersync/raw/master/sersync2.5.4_64bit_binary_stable_final.tar.gz -O /tmp/sersync.tar.gz
# 步骤2:创建安装目录(统一管理,便于维护)
mkdir -p /usr/local/sersync
# 步骤3:解压安装包(提取核心文件)
tar -zxvf /tmp/sersync.tar.gz -C /usr/local/sersync --strip-components=1
# 步骤4:验证安装(预期:看到 sersync2 可执行文件)
ls -l /usr/local/sersync/sersync2
# 输出:-rwxr-xr-x 1 root root ... sersync2 (有x权限即正常)
2. 源主机配置sersync
bash
复制代码
cat > /usr/local/sersync/confxml.xml << 'EOF'
<?xml version="1.0" encoding="ISO-8859-1"?>
<head version="2.5">
<host hostip="localhost" port="8008"></host> <!-- 本地监控端口,无需修改 -->
<debug start="false"/> <!-- 调试模式:false=关闭(生产环境),true=开启(调试) -->
<fileSystem xfs="true"/> <!-- 文件系统:Rocky 9默认XFS,设为true;EXT4设为false -->
<!-- 文件过滤规则:排除无需同步的文件类型 -->
<filter start="true">
<exclude expression="(.*)\.tmp"></exclude> <!-- 排除.tmp临时文件 -->
<exclude expression="(.*)\.log"></exclude> <!-- 排除.log日志文件(可选) -->
<exclude expression="\.DS_Store"></exclude> <!-- 排除MAC系统隐藏文件 -->
</filter>
<!-- inotify监控事件配置(与inotify+rsync一致) -->
<inotify>
<delete start="true"/> <!-- 监控删除事件 -->
<createFolder start="true"/> <!-- 监控目录创建事件 -->
<createFile start="true"/> <!-- 监控文件创建事件 -->
<closeWrite start="true"/> <!-- 监控文件写入完成事件(避免同步未写完的文件) -->
<moveFrom start="true"/> <!-- 监控文件移出事件 -->
<moveTo start="true"/> <!-- 监控文件移入事件 -->
<attrib start="true"/> <!-- 监控属性变更事件(权限/时间戳) -->
<modify start="true"/> <!-- 监控文件内容修改事件 -->
</inotify>
<sersync>
<!-- 源主机同步目录(与inotify+rsync一致) -->
<localpath watch="/data/sync_dir">
<!-- 目标主机配置:ip=目标IP,name=同步目录(无需写全路径) -->
<remote ip="10.0.0.15" name="sync_dir"/>
<!-- 多目标同步示例(如需同步到多台,复制该行修改IP即可) -->
<!-- <remote ip="10.0.0.16" name="sync_dir"/> -->
</localpath>
<!-- rsync同步参数配置(与inotify+rsync一致) -->
<rsync>
<commonParams params="-avz --delete"/> <!-- 核心同步参数 -->
<auth start="false"/> <!-- 关闭rsync认证(用SSH免密即可) -->
<timeout time="100"/> <!-- 同步超时时间(秒) -->
<ssh start="true"/> <!-- 启用SSH免密同步(必须开启,与之前的免密配置适配) -->
</rsync>
<!-- 日志配置:自动轮转,避免日志过大 -->
<log logfile="/var/log/sersync.log" logsize="10000000"/> <!-- 10MB自动切割 -->
</sersync>
</head>
EOF
# 验证配置文件(XML语法检查,避免配置错误)
xmllint /usr/local/sersync/confxml.xml
# 预期:输出配置文件内容,无 XML parse error 报错。
3. 源主机启动&持久化sersync
bash
复制代码
# 步骤1:先停止inotify-sync服务(避免端口/监控冲突)
systemctl stop inotify-sync
# 步骤2:创建sersync的systemd服务文件
cat > /usr/lib/systemd/system/sersync.service << 'EOF'
[Unit]
Description=Sersync Real-Time Sync Service
After=network.target sshd.service
Documentation=https://github.com/wsgzao/sersync
[Service]
Type=forking
# sersync以守护进程运行,必须设为forking
# 启动命令解释:
# -d:后台运行;-r:首次启动全量同步;-o:指定配置文件路径
ExecStart=/usr/local/sersync/sersync2 -d -r -o /usr/local/sersync/confxml.xml
Restart=always
# 崩溃自动重启
RestartSec=3
User=root
StandardOutput=append:/var/log/sersync.log
StandardError=append:/var/log/sersync.log
[Install]
WantedBy=multi-user.target
EOF
# 步骤3:启动服务并设置开机自启
systemctl daemon-reload
systemctl start sersync
systemctl enable sersync
systemctl status sersync
# 状态验证标准:
# 1. active (running);
# 2. ps -ef | grep sersync2 能看到进程;
# 3. 无报错信息。
4. 详细验证sersync
bash
复制代码
# 场景1:高频修改文件(验证事件合并)
# 源主机执行(1秒内修改3次同一文件)
for i in {1..3}; do
echo "高频修改第${i}次" >> /data/sync_dir/high_freq.txt
sleep 0.3
done
# 目标主机验证(预期:文件包含所有修改内容)
ssh root@10.0.0.15 "cat /data/sync_dir/high_freq.txt"
# 场景2:查看sersync日志(验证事件合并)
# 源主机执行
tail -n 5 /var/log/sersync.log
# 预期:仅看到1次rsync调用记录(3次修改合并为1次),无重复同步。
# 场景3:批量创建文件(验证高频同步效率)
# 源主机执行(1秒创建10个文件)
for i in {1..10}; do
echo "批量文件${i}" > /data/sync_dir/batch_${i}.txt
sleep 0.1
done
# 目标主机验证(预期:10个文件均存在,内容一致)
ssh root@10.0.0.15 "ls /data/sync_dir/batch_*.txt | wc -l"
# 输出:10(表示10个文件均同步成功)
六、完整运维手册
1. 服务启停命令
bash
复制代码
# inotify+rsync 服务
systemctl start inotify-sync # 启动
systemctl stop inotify-sync # 停止
systemctl restart inotify-sync # 重启
systemctl status inotify-sync # 查看状态
# sersync 服务
systemctl start sersync # 启动
systemctl stop sersync # 停止
systemctl restart sersync # 重启
systemctl status sersync # 查看状态
2. 常见问题排错
| 问题现象 |
排查步骤 |
解决方法 |
| inotify-tools安装失败 |
执行 yum repolist |
grep epel,查看EPEL仓库是否启用 |
| 同步提示Permission denied |
源主机执行 ls -ld /data/sync_dir,目标主机执行同样命令 |
chmod 755 /data/sync_dir && chown root:root /data/sync_dir |
| SSH免密失效 |
源主机执行 ssh root@10.0.0.15,查看是否需要输密码 |
重新执行 ssh-copy-id root@10.0.0.15 |
| sersync启动失败 |
执行 journalctl -u sersync -n 20,查看报错;执行 xmllint 检查XML配置 |
修正XML配置语法错误,确保 适配文件系统 |
| 同步无反应 |
源主机执行 ps -ef |
grep inotifywait(或sersync2),查看进程是否存在 |
3. 日志管理
bash
复制代码
# 日志轮转配置(以inotify_sync.log为例)
cat > /etc/logrotate.d/inotify_sync << 'EOF'
/var/log/inotify_sync.log {
daily # 按天轮转
rotate 7 # 保留7天日志
compress # 压缩旧日志
missingok # 日志不存在时不报错
notifempty # 空日志不轮转
create 644 root root # 轮转后创建新日志,权限644
}
EOF
# sersync日志轮转(同理)
cat > /etc/logrotate.d/sersync << 'EOF'
/var/log/sersync.log {
daily
rotate 7
compress
missingok
notifempty
create 644 root root
}
EOF
sersync 与 inotifywait+rsync 方案优缺点对比表
| 对比维度 |
sersync 方案 |
inotifywait + rsync 方案 |
| 系统兼容性 |
仅兼容 CentOS6/7 等旧系统;在 Rocky9/CentOS9 上因 glibc 版本过高,必然触发 core dump 崩溃 |
完全兼容所有主流 Linux 发行版(包括 Rocky9、CentOS9、Ubuntu22.04 等),无依赖兼容性问题 |
| 功能完整性 |
集成实时监控+rsync 同步+失败重试+日志记录+插件扩展(如 CDN 刷新) |
核心功能覆盖(实时监控+rsync 同步),可通过脚本自定义日志、重试逻辑,无插件扩展 |
| 维护成本 |
项目多年未更新,无官方维护;遇到问题无解决方案,需手动修改源码适配 |
基于系统原生工具(inotify-tools/rsync),工具本身由系统发行版维护,问题可通过官方文档解决 |
| 配置复杂度 |
配置文件为 XML 格式,标签多、语法严格,易因标签未闭合等导致启动失败 |
配置通过 Shell 脚本实现,逻辑直观,参数简单,新手易上手 |
| 资源占用 |
二进制程序,占用内存较小(约 1-2MB) |
脚本+两个进程(inotifywait/rsync),内存占用略高(约 3-5MB),可忽略不计 |
| 生产环境可用性 |
不推荐用于生产环境,兼容性问题导致服务不稳定,易中断同步 |
推荐用于生产环境,稳定可靠,是 Rocky9/CentOS9 实时同步的主流方案 |
| 故障排查难度 |
崩溃时仅输出 core dump 栈追踪,无明确报错信息,排查困难 |
可通过日志文件直接查看同步失败原因(如网络不通、权限不足),排查简单 |
| 扩展能力 |
支持插件机制,但插件功能老旧,无新版系统适配 |
可通过 Shell 脚本自由扩展(如增加邮件告警、多目标同步、过滤特定文件) |
总结建议
| 适用场景 |
推荐方案 |
| 旧系统(CentOS6/7)、需要插件功能 |
sersync |
| 新系统(Rocky9/CentOS9/Ubuntu22.04)、生产环境稳定需求 |
inotifywait + rsync |