rsync -a 备份后硬链接变成独立文件
rsync 的归档模式不包含硬链接保留。用设备号和 inode 确认关系,再以 -aH 在同一次传输中备份;旧目标的多余链接仍需单独核验。
用 rsync -a 备份目录后,两个原本指向同一文件的名称变成了两份独立文件。内容看起来相同,但在目标端原地修改其中一份,另一份不再一起变化,磁盘占用也可能增加。
归档模式 -a 不包含硬链接保留。要在目标重建源文件之间的硬链接关系,需要显式使用 -H,而且相关名称必须进入同一次传输集合。以下按 Linux 上 rsync 的当前规则说明,属性检查使用 GNU stat;目标文件系统需支持普通文件硬链接,相关目标路径也必须位于同一文件系统。
先确认源端确实是同一文件
挑出一对预期互为硬链接的普通文件,以实际路径替换下面的占位值:
stat -c '%d:%i links=%h %n' -- \
/srv/source/path-a.dat /srv/source/path-b.dat
%d 是设备号,%i 是 inode,%h 是硬链接数。两个名称在同一台机器上拥有相同的设备号与 inode,才说明它们引用同一个文件。仅凭内容、大小或 inode 单项相同都不够。
在目标端对对应的两个名称做同样检查:
stat -c '%d:%i links=%h %n' -- \
/srv/backup/path-a.dat /srv/backup/path-b.dat
比较的是每一端内部的关系,不要求备份端的 inode 数值等于源端。目标端这两个文件的设备与 inode 不同,而源端相同,才是这里要处理的链接关系丢失。
示例不使用 -L 跟随符号链接。符号链接是另一种对象,-a 中的 -l 已处理符号链接本身,不能用它替代大写 -H。
在同一次传输中保留硬链接
先准备一个空的独立备份目录,不覆盖已有恢复点。源目录应是稳定副本或满足应用一致性要求的快照;正在写入的数据库目录不能因加了 -H 就当作可恢复备份。
以下所有路径均为占位。/srv/backup-new/ 应已创建、确认可写且不在源目录中。先预演:
rsync -aH --dry-run --itemize-changes -- \
/srv/source/ /srv/backup-new/
-H 让 rsync 查找源集合中的硬链接,并在目标把对应文件链接起来。--itemize-changes 的更新类型 h 表示硬链接操作。检查路径范围、读取错误和计划变更后,再决定是否执行。
确认目标可恢复、预演没有意外覆盖,且源仍保持稳定后,正式同步使用相同参数,仅移除 --dry-run:
rsync -aH --itemize-changes -- \
/srv/source/ /srv/backup-new/
这里没有删除目标独有文件的选项,也没有 --inplace。执行用户权限仍影响属主等属性的保留;-aH 不会自动包含 ACL 和扩展属性,若备份契约要求这些属性,需另行核对文件系统与相应选项。
只传入一个名称,无法保留集合外的关系
假设 path-a.dat 和 path-b.dat 是源端同一文件的两个名称,但命令只传入前者,或过滤规则排除了后者,rsync 无法在这次传输中建立两者的对应关系。将两部分拆成互不重叠的两个 rsync 调用,也不能指望 -H 自动发现另一批里的名称。
因此,应把需要共同恢复的名称包含在同一次传输集合中。不要为凑齐链接关系直接扩大到整台机器;先确定备份范围及那些名称的实际位置。--files-from 清单、排除规则和多个源参数都应一起审核。
-H 的查找会增加资源需求,大目录可先在有代表性的非生产副本中评估。它不会把内容相同但原本独立的文件自动去重成硬链接;内容相同不是建立共享修改关系的依据。
旧目标可能保留多余的硬链接
即使使用 -H,也不能保证一个已有目标目录里的硬链接拓扑与源端完全一致。目标原本多出的硬链接不会被 rsync 专门逐一拆开;某些内容更新可能打断链接,但不能把这种附带效果当作完整清理策略。--link-dest 也可能引入额外共享关系。
对链接关系要求严格的恢复点,使用空的新目录更容易核验。不要为了避免链接被打断就加入 --inplace:它会直接修改目标文件,其他硬链接名称可能同时看到变化,甚至影响传输集合之外的文件。
同步结束后重新检查几对预期共享文件的设备与 inode,同时检查预期独立的文件没有意外共享。结合 rsync 的退出状态、内容校验和所需属性验收;仅看 du 的大小变小不能证明备份正确。
保留旧备份直到新恢复点验证通过。若写入了已有目录并改变内容或链接关系,取消 -H 不会恢复原状态;回退依赖同步前保存的可恢复备份。不要对唯一备份手工批量拆链接或重新链接来“修好”统计数字。


