生产环境增量备份优先用 rsync,因其对硬链接、稀疏文件、权限及xattrs的处理成熟稳定;Python标准库无法比拟,自行实现易在跨时区、NFS或不同文件系统间误判;必须用Python时应封装rsync或使用pyrsync。

增量备份该用 rsync 还是纯 Python?
直接说结论:生产环境下,优先选择
rsync。这倒不是因为它有多“高级”,而是因为它对硬链接、稀疏文件、权限、xattrs 这些细节的处理,已经打磨了数十年。相比之下,Python 标准库根本没法比。自己上手写
shutil.copy2 加
os.stat 对比 mtime 的方案,很容易在跨时区、NFS、ext4 或 btrfs 之间漏判甚至误判。如果实在必须用 Python(比如要嵌入 GUI 或者没有 shell 环境),建议用
pyrsync,或者直接封装
rsync 命令,别从零开始写校验逻辑,那是自找麻烦。
rsync --delete --archive --hard-links 的实际含义
这条命令并不是什么“万能同步”的咒语。每个 flag 背后都有明确的副作用,没搞清楚就乱用,很容易丢数据:
-
--archive 等价于
-rlptgoD,会保留所有元数据。但问题在于,如果目标文件系统不支持 setgid 或 ACL(比如 FAT32 或某些 NAS),
rsync 会直接静默失败,而且不报错。
-
--hard-links 要求源和目标必须在同一个挂载点下才能生效。一旦跨分区,它会自动退化为普通拷贝,而且不会给你任何警告。
-
--delete 会删除目标中源没有的文件。这里有个特别容易踩的坑:如果源路径末尾少了那个
/(比如写成
/src 而不是
/src/),
rsync 会把整个
/src 目录当成一个文件来同步,结果就是目标被清空。
如何避免 rsync 把备份变成“单点故障”
镜像同步和真正的备份,是两码事。真正的增量备份需要保留历史快照,而
rsync 默认只做“当前状态同步”。常用的解法是配合
--link-dest 和硬链接:
- 每次备份到一个新目录(比如
backup_20240520),并指定上一次备份目录为
--link-dest=../backup_20240519。
- 相同文件会被硬链接复用,节省空间;不同的文件则真实写入。
- 关键限制:源和所有备份目录必须在同一个文件系统上,否则硬链接会失效,直接变成全量复制。
- 别依赖
rsync --backup,它只备份被覆盖的单个文件,不会保留完整的历史记录。
Python 脚本调用 rsync 时最容易崩的三个点
用
subprocess.run 调
rsync,看起来简单,但实际踩坑率极高:
- 路径含空格或中文?必须用
shell=False 加列表传参,不能拼字符串——否则
shlex.split() 会错误切分。
- 忽略
check=True:
rsync 返回 23 表示部分文件失败(比如权限不足),但 Python 默认不抛异常。
- 没捕获
stderr:当
rsync 因
--delete 删除大量文件时,进度输出走
stderr,不读取会导致缓冲区满、进程卡死。
硬链接跨文件系统、
rsync 的 exit code 含义、
--link-dest 路径必须是相对目标目录的相对路径——这些细节不查手册,跑一两次就出事。
本文转载于:https://www.php.cn/faq/2819812.html 如有侵犯,请联系zhengruancom@outlook.com删除。
免责声明:正软商城发布此文仅为传递信息,不代表正软商城认同其观点或证实其描述。