You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

rsync结合--link-dest与--hard-links备份时处理硬链接目录结构异常的问题咨询

我自己搭了一套基于rsync的夜间增量备份方案,用--link-dest只同步新增/变更的内容,再加--hard-links来忠实还原源目录里的硬链接结构——这两个参数配合起来既能省网络流量,又能少占存储空间,一直用着都挺顺的。

最近我想整理"media"目录下几百个分散在各子目录里的媒体文件,想着最省空间的办法应该是先建一个平行的目录结构,用硬链接指向原文件,然后在新目录里随意移动这些硬链接(本来以为除了目录条目不会额外占空间),最后把新的目录结构替换掉原来的"media"目录就行。

结果出乎意料:这个操作触发了rsync大量复制文件、传输数据的行为。我用--dry-run仔细排查后发现,rsync的处理逻辑有点反直觉:它会先把新目录里的文件同步到备份里,然后再给旧目录里的对应文件创建硬链接(相当于丢弃之前备份里的旧文件副本),而不是反过来——直接给新目录里的文件创建指向旧备份中已有文件的硬链接。

我观察到的规律

看起来rsync是按字母顺序遍历源目录,再去对比上一次的备份内容。对于inode相同的文件(也就是硬链接),rsync先处理到的那个会决定是链接到旧备份还是重新复制,后面遇到的同inode文件则会链接到这个第一个被处理文件的备份副本。如果先碰到新目录里的文件,就会触发复制;如果先碰到旧目录里的文件,就会直接链接到旧备份里的已有文件。

我想请教的两个问题

  • 除了手动调整目录名称让排序符合预期之外,有没有其他办法能解决这个问题?(我觉得rsync其实可以先扫描所有同inode的源文件,检查其中是否有任何一个在目标备份里有对应项,而不是只看第一个被遍历到的文件)
  • 有没有办法不用手动修改备份里的目录名称?我原本的需求是把MyDir下的文件移到不同子目录,所以建了MyDir2,在里面创建指向MyDir文件的硬链接并整理结构,现在整理完了想让新结构用回MyDir这个名字。但直接修改MyDir会触发文件复制,目前我找到的临时办法是:在源目录和最后一次备份里都删掉MyDir,再把MyDir2改名为MyDir,但总觉得有点麻烦。

测试中的困惑

后来我用小例子复现这个场景,结果却完全符合预期——不管遍历顺序如何,源里新增的硬链接在目标备份里都会生成对应的硬链接,没有出现复制文件的情况。这就让我更懵了:难道是备份的大小影响了rsync的行为?我实际要处理的备份是3TB规模,包含80万个文件、15万个目录,而测试的小例子只有几个文件。

测试的具体操作与输出

我做的测试步骤是这样的:
初始源目录结构:

source
└── dir2
    ├── file1
    └── file2

先把source同步到dest1:rsync --archive source/ dest1/

然后在source里新建dir1和dir3,里面分别创建指向file1和file2的硬链接:

source
├── dir1
│   └── file1
├── dir2
│   ├── file1
│   └── file2
└── dir3
    └── file2

接着运行备份命令:

rsync --archive --link-dest ../dest1 --hard-links --itemize-changes source/ dest2/

输出结果是:

created directory dest2
cd..t...... ./
cd+++++++++ dir1/
hf+++++++++ dir1/file1 => dir2/file1
cd+++++++++ dir3/
hf+++++++++ dir3/file2 => dir2/file2

和实际备份的情况完全不同,dest2里没有生成新文件,只有硬链接。

备注:内容来源于stack exchange,提问作者ciobi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.20 07:18:05