rsync 是一款非常实用的工具。它可以帮你节省复制现有数据的时间和精力。它是许多镜像站点的支柱,也用于各种备份解决方案。
只有一个问题:为了提高效率,它可能会错过某些更改。rsync 通常会检查候选文件的大小和修改时间,如果两端的文件大小和修改时间相同,则不再进行任何处理。它不会再受到任何关注,而是转向其他操作。
你可能会想:“那又怎么样?所有文件在写入时,至少都会改变其修改时间 (mtime)。这就是修改时间 (mtime) 的意义所在。”
然而…我正在写这篇文章,我们就在这里。
那些眼尖的观察者可能已经在想“哦,比特腐烂”之类的问题了,比如某个文件在“静止”状态下不知何故损坏了。这些观察者是对的!这确实是一个需要担心的问题,尤其是在使用固态硬盘 (SSD) 存储数据,而这些固态硬盘并非一直处于通电状态的情况下。
但不,这是你必须担心的事情,远不止于此。这是一条你可能没考虑到的“潜行路径”。我没考虑过。
来,我们来做个小实验。如果你有一台比较新的 x86_64 Debian 系统,并且已经用 rsync 备份了整套系统一两年了,那就帮我做点什么吧。
帮我在 /usr/lib/x86_64-linux-gnu/libfribidi.so.0.4.0 上运行你最喜欢的文件哈希工具。给它一个 sha256sum 或其他什么,如果你觉得够大胆,甚至可以用 md5sum。然后记下文件的修改时间。
现在挂载其中一个备份,并对备份设备上的文件版本执行相同的操作。看到什么了吗?有什么异常吗?
相同的时间、相同的大小……还有不同的哈希值,对吧?在经历了 SSD 数据丢失这件事后,我在我的很多机器上都发现了这个问题。
显然,某个地方发生了一些不寻常的事情,而它从那以后就一直没有被你的 rsync 运行所注意到。我还没有深入研究过这个问题的软件包历史记录,以查明它发生的时间和地点,以及(更重要的是)它是如何发生的。这确实很不寻常。
如果你现在正焦头烂额,那么还有一线希望。rsync 的 -I 和 -c 选项承诺不使用快速方法,而是对文件进行校验和。这种方法比较慢,所以通常情况下你不会想这么做,但每隔一段时间就把这个选项添加到你执行的一系列操作中也不错。
需要指出的是,第一次执行强制校验和运行时,–dry-run 会在错误发生之前让你看到变化,这样你就可以判断哪个版本是正确的!理论上,你的*源*文件可能会损坏,如果你只是复制其中一个文件过去,那么你的备份就已经损坏了。
熵不是很有趣吗?