基于rsync、inotify-tools的文件同步
一 总体流程
- 准备工作:确认两台服务器网络互通,确定需要同步的源目录和目标目录,检查并安装 rsync、inotify-tools 工具。
- 配置免密登录:在源服务器生成 SSH 密钥对,将公钥复制到目标服务器,实现免密登录(避免同步时输入密码)。
- 测试 Rsync 基础同步:手动执行一次 rsync 命令,验证源目录到目标目录的基础同步功能是否正常。
- 编写监控脚本:创建脚本,利用 inotify 监控源目录的变化,当有文件新增 / 修改 / 删除时,自动触发 rsync 进行同步。
- 设置自动运行:将脚本配置为系统服务或添加到开机启动,确保监控和同步能持续运行。
二 准备工作
软件安装:
apt:sudo apt update && sudo apt install -y rsync inotify-toolsyum:sudo yum install -y rsync inotify-tools
检查安装结果:
- 检查
rsync:rsync --version(能显示版本信息即为成功) - 检查
inotify-tools:inotifywait --version(能显示版本信息即为成功)
遇到的问题:
1. Unable to find a match: inotify-tools
-
换源安装:失败, 有冲突
-
手动安装:
# 如果还没安装编译工具,先执行这句 sudo yum install -y gcc make automake autoconf libtool wget https://github.com/inotify-tools/inotify-tools/archive/refs/tags/3.20.1.tar.gz -O inotify-tools-3.20.1.tar.gz tar -zxvf inotify-tools-3.20.1.tar.gz cd inotify-tools-3.20.1/ autoreconf -ivf ./configure make sudo make install ---- # inotifywait --help inotifywait 3.20.1
三 配置免密登录
- 生成秘钥对:
ssh-keygen -t rsa -P "" - 将源服务器的公钥复制到目标服务器:
ssh-copy-id 目标服务器用户名@目标服务器IP - 如果2不好操作,可以手动处理:
- 复制公钥,到目标服务器
- 手动追加:
cat id_rsa.pub >> ~/.ssh/authorized_keys
- 测试免密登录:
ssh 目标服务器用户名@目标服务器IP,exit退出
四 文件同步脚本
/xqd/mine-shell/folder_rync/realtime_sync.sh
#!/bin/bash
##############################################################################
# 文件名称: realtime_sync.sh
# 功能描述: 实时监控源目录文件变化并同步至目标服务器(用于备份)
# 运行环境: Linux (依赖 inotify-tools, rsync)
##############################################################################
####################### 基本配置 ##########################
SRC="/xqd/folder_sync/" # 源目录(A服务器)
DEST="username@ip:/xqd/folder_sync/" # 目标目录(B服务器)
LOG_DIR="/xqd/mine-shell/folder_rync/logs" # 日志目录
LOG_FILE="$LOG_DIR/folder_sync.log" # 日志文件
EVENTS="modify,create,delete,move,attrib" # 监听事件类型
DELAY=3 # 防抖延迟(秒)
####################### 初始化部分 ##########################
# 确保日志目录存在
mkdir -p "$LOG_DIR"
touch "$LOG_FILE"
chmod 644 "$LOG_FILE"
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >> "$LOG_FILE"
}
log "------------------------------------------------------"
log "脚本启动,开始初始化同步(仅传输差异内容)"
# 首次全量同步
if rsync -az --delete-after --partial --inplace "$SRC" "$DEST" >> "$LOG_FILE" 2>&1; then
log "初始化同步完成"
else
log "初始化同步时出现错误"
fi
# 防抖标志位
waiting=0
####################### 实时监控与同步逻辑 ##########################
log "开始监听目录: $SRC"
# 这里的核心:inotifywait 通过“管道”把事件不断输出到 while 循环
# 管道让整个监控流不占用前台输出,也不会阻塞终端
# -m 表示持续监听
# -r 表示递归
# -q 静默模式,不打印多余信息
# --format 指定只输出触发文件路径
inotifywait -mrq --format '%w%f' -e "$EVENTS" \
--exclude '\.swp$|~$|^4913$|\.swx$' "$SRC" | while read -r triggered_file; do
if [ $waiting -eq 0 ]; then
waiting=1
(
sleep $DELAY
log "检测到变化,触发同步:$triggered_file"
if rsync -az --delete-after --partial --inplace "$SRC" "$DEST" >> "$LOG_FILE" 2>&1; then
log "同步完成(触发源:$triggered_file)"
else
log "同步出错(触发源:$triggered_file)"
fi
waiting=0
) &
fi
done
基于脚本的一些命令:
- 执行权限:
chmod +x /xqd/mine-shell/folder_rync/realtime_sync.sh - 后台启动:
nohup ./realtime_sync.sh >/dev/null 2>&1 & - 关闭进程:
pkill -f realtime_sync.sh - 查看进程:
ps -ef | grep realtime_sync.sh | grep -v grep: 两个进程 一个父一个while子 - 查看日志:
tail -f /xqd/mine-shell/folder_rync/logs/folder_sync.log\ - 搜索包含"错误"的日志:
重启动脚本:restart_sync.sh
#!/bin/bash
# 终止正在运行的脚本进程
pkill -f "realtime_sync.sh"
# 等待几秒确保进程退出
sleep 3
# 启动新的脚本实例(后台运行,输出重定向)
nohup /xqd/mine-shell/folder_rync/realtime_sync.sh >/dev/null 2>&1 &
可以定时重启:
0 2 * * * /path/to/restart_sync.sh
五 使用系统自带 logrotate 进行日志切割
1创建自定义配置文件
路径:/etc/logrotate.d/folder_sync
/xqd/mine-shell/folder_rync/logs/folder_sync.log {
# 每天轮转一次
daily
# 保留7个历史日志
rotate 7
# 压缩旧日志
compress
# 延迟一天再压缩
delaycompress
# 忽略文件不存在
missingok
# 空文件不轮转
notifempty
# 新文件权限设置为644,属主和属组为root
create 644 root root
sharedscripts
postrotate
# 日志切割后重载服务(可选)
systemctl reload folder-sync.service >/dev/null 2>&1 || true
endscript
}
2 验证配置
logrotate -d /etc/logrotate.d/folder_sync
-d是 debug 模式,不实际切割,只显示将执行的操作。
3 手动测试切割
logrotate -f /etc/logrotate.d/folder_sync
六 用 systemd 管理
/etc/systemd/system/folder-sync.service
shell
[Unit]
Description=Folder realtime sync service
After=network.target
[Service]
ExecStart=/xqd/mine-shell/folder_rync/realtime_sync.sh
Restart=always # 意外退出时自动重启
# User=root # 根据实际用户调整
StandardOutput=null # 输出重定向到日志(或脚本内已处理)
StandardError=journal
[Install]
WantedBy=multi-user.target
启用
systemctl daemon-reload
systemctl enable folder-sync.service
systemctl start folder-sync.service
systemctl status folder-sync.service
2025-11-11整理 by Vic.xu
GitHub 登录
Gitee 登录
QQ 登录