脚本如何双向同步两个目录

wen 实用脚本 28

原理、工具与实战指南

目录导读

  1. 什么是双向同步?为什么需要它?
  2. 双向同步 vs 单向同步 vs 镜像同步:核心区别
  3. 主流双向同步工具与脚本方案
    • rsync + 自定义脚本
    • unison(专业双向同步工具)
    • inotify + rsync 实时触发
    • 使用 rclone bisync 命令
    • 云存储场景下的双向同步
  4. 实战:用 bash 脚本实现两个目录的双向同步(含冲突处理)
  5. 常见问题与问答
  6. 总结与最佳实践

什么是双向同步?为什么需要它?

双向同步(Bidirectional Sync)指的是两个目录(本地与远程、本地与本地、或云端与本地)能够互相检测变化,并确保最终内容完全一致,这意味着:在 A 目录中新增、修改或删除的文件,会自动同步到 B 目录;反之,B 目录的变化也会同步回 A 目录。

脚本如何双向同步两个目录

使用场景包括:

  • 开发者在本地与服务器之间同步代码
  • 多台电脑共享工作文件夹
  • NAS 与移动设备之间的文件管理
  • 团队协作中共享配置或数据文件

核心痛点:双向同步最怕“冲突”——当同一文件在两端同时被修改,脚本需要决定保留哪个版本,这也是双向同步比单向同步复杂的根本原因。


双向同步 vs 单向同步 vs 镜像同步

类型 方向 行为 典型工具
单向同步 A → B 只从源复制到目标,目标的变化不会影响源 rsync 默认模式
镜像同步 强制覆盖 始终保持目标与源完全一致,目标本地修改会被覆盖 rsync --delete
双向同步 A ↔ B 两端互相合并,需处理冲突 unisonrclone bisync

误区提醒:很多人用 rsync 加上两个方向的指令来模拟双向同步,但这种做法无法处理冲突。

rsync -av A/ B/
rsync -av B/ A/

若同一文件在两处都被修改,第二次运行会直接覆盖第一次的变更,导致数据丢失。


主流双向同步工具与脚本方案

1 rsync + 自定义脚本(适合简单场景)

使用 rsync 结合文件修改时间戳检查,写一个判断逻辑:

#!/bin/bash
# 简单双向同步脚本(不处理冲突)
DIR1="/path/to/dir1"
DIR2="/path/to/dir2"
# 从 dir1 到 dir2(排除冲突检测)
rsync -av --update "$DIR1/" "$DIR2/"
rsync -av --update "$DIR2/" "$DIR1/"

缺点--update 只保留较新版本,如果两个文件的时间戳相同但内容不同,会静默覆盖,不推荐用于重要数据。

2 Unison(专业双向同步工具)

Unison 是专门为双向同步设计的工具,跨平台、支持 SSH,且能自动检测冲突并提示用户选择。

安装

sudo apt install unison  # Linux
brew install unison      # macOS

基本使用

unison /path/to/dir1 ssh://user@host//path/to/dir2

优点:自动记录同步状态(存档文件),冲突时弹出交互界面;也可通过 -batch 参数实现静默同步(使用预设策略)。

脚本示例(无交互)

#!/bin/bash
unison /local/dir /remote/dir -batch -auto -ignore "Name *.tmp"
  • -batch:静默模式
  • -auto:自动解决冲突(优先选择较新文件)

3 inotify + rsync 实时双向同步

利用 Linux 内核的 inotify 机制监控文件变化,触发 rsync,这种方案适合低延迟场景。

工具组合inotifywait + rsync

#!/bin/bash
SRC="/data/dir1"
DST="/data/dir2"
while true; do
  inotifywait -r -e modify,create,delete,move "$SRC"
  rsync -av --delete "$SRC/" "$DST/"
done

注意:这个脚本只监控了 dir1 的变化,若要双向,需要同时监控两端,并避免陷入“重复触发”循环——即 A 同步到 B 时,B 的变化又触发回 A,解决方案:使用标志文件或延时检测。

4 rclone bisync(云端首选)

如果你需要同步本地与云存储(如 Google Drive、OneDrive、S3),rclonebisync 子命令是最佳选择。

示例

rclone bisync /local/folder remote:folder --resync --verbose --log-file=/var/log/sync.log
  • --resync:首次运行时标记为已知状态
  • 它会自动记录同步状态,冲突时默认保留较新版本(可配置)

独特优势:支持几乎所有云存储协议,且能增量同步,节省带宽。

5 编写纯 bash 双向同步脚本(含冲突处理)

如果你想自己控制逻辑,这里提供一个稍微完善的脚本,基于文件 MD5 校验与修改时间对比。

#!/bin/bash
# 双向同步脚本(内嵌冲突处理)
DIR_A="/mnt/data/a"
DIR_B="/mnt/data/b"
LOG="/var/log/twoway_sync.log"
log() {
  echo "$(date '+%Y-%m-%d %H:%M:%S') $1" >> "$LOG"
}
# 检测文件变更并同步(从 A 到 B)
rsync -av --checksum --backup --backup-dir="$DIR_B/.sync-backup" "$DIR_A/" "$DIR_B/"
# --checksum 基于内容校验,而非时间戳,可避免误判
# --backup 在被覆盖前备份到备份目录
# 检测从 B 到 A(排除由上面同步所产生的变更)
rsync -av --checksum --backup --backup-dir="$DIR_A/.sync-backup" "$DIR_B/" "$DIR_A/"
log "双向同步完成"
# 冲突处理说明:若同一文件在两端被修改,rsync根据--checksum保留最后写入版本
# 更安全的做法:将冲突文件移动到 .conflict 目录,由用户决定

改进建议:可结合 diffcmp 检测冲突文件,并将其重命名为 filename.conflict,不自动覆盖。


常见问题与问答

Q1:双向同步和备份有什么区别?
A:备份通常是单向的(从源到目标),目的是数据恢复;双向同步则是两端保持相同,适用于协作环境,如果误删文件,双向同步会删除另一端,而备份不会。

Q2:用 rsync 做双向同步,如何避免循环触发?
A:可以配合文件锁或条件检测,在同步前创建锁文件,同步完成后删除;或者使用 --exclude 排除同步产生的临时文件。

Q3:哪个工具适合 Windows?
A:Windows 下推荐使用 unison(有 GUI 版本)或 rclone(命令行),也可以使用 FreeFileSync(图形界面双向同步软件)。

Q4:双向同步时,文件被锁定怎么办?
A:大多数工具会跳过无法读取的文件,可以在脚本中加入 lsof 检测文件被占用时延迟重试。

Q5:如何实现定时自动双向同步?
A:将脚本加入 cron(Linux)或任务计划程序(Windows)。0 */2 * * * /home/user/twoway_sync.sh 每两小时同步一次。

Q6:是否需要保留同步日志?
A:强烈建议开启日志,日志可以帮助你追溯冲突原因,并在同步失败时快速定位问题,日志文件建议设置日志轮替(logrotate)。


总结与最佳实践

双向同步并非一成不变的选择,而应根据数据重要性、实时性要求和网络环境决定:

场景 推荐工具 原因
本地双目录同步 Unison 可交互处理冲突,可靠
本地到远程服务器 rsync + 定时任务 简单高效
实时同步需求 inotify + rsync 低延迟,但需防循环
云端同步(Google Drive 等) rclone bisync 支持协议广泛,冲突处理强
大量文件(百万级) 建议拆分目录或用数据库索引同步 文件系统遍历性能瓶颈

最终建议

  1. 首次同步务必使用 --dry-run 或模拟模式,确保理解扩散范围。
  2. 定期验证同步结果:可用 diff -r 对比两端内容。
  3. 重要数据保留备份(版本历史):即使双向同步,也应额外做快照备份。
  4. 文档化你的同步策略:包括冲突谁优先、忽略哪些文件(如缓存、系统文件)。

双向同步看似简单,但细节决定成败,希望本文能帮你构建一个稳定、可维护的双向同步方案,如果你在使用过程中遇到特殊的冲突案例,欢迎在评论区交流——脚本世界的“双向奔赴”,向来是一场精心设计的平衡艺术。

抱歉,评论功能暂时关闭!