如果旧文件已存在,如何让 rsync 使用 --link-dest 选项链接相同的文件?

如果旧文件已存在,如何让 rsync 使用 --link-dest 选项链接相同的文件?

人们可能认为--link-dest“访问相同的文件”在所有情况下都适用。但当文件存在时,即使文件已过期/具有不同的内容,它也不会发生。

正因为如此,从 rsync 手册页来看--link-dest

“当复制到空目标层次结构时,此选项效果最佳,因为 rsync 将现有文件视为确定文件(因此当目标文件已存在时,rsync 从不查找链接目标目录)”

这意味着如果y/file存在与源相同并且z/file已过时,

rsync -a --del -link-dest=y source:/file z

将导致使用两个 inode(以及两倍的磁盘空间),y/file并且z/file,它们将具有相同的内容和日期戳。

我遇到这个问题是因为我基本上每天运行一次这个脚本来进行备份:

mv $somedaysago $today; 
yest=$today; today=`date +%Y%m%d`;
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today

因为我的备份跨越多达 10M 个文件,所以这样做rm -rf $olddir; rsync source:$dir newdir会花费太长时间(特别是当每天只有 0.5% 的文件发生更改时,仅仅为了处理 50K 新的或更改的文件就会导致删除和创建 10M 目录条目,这将使我的第二天的备份未及时完成)。

这是情况的演示:

a是我们的来源,1通过4是我们编号的备份:

$ mkdir -p 1 2; echo foo > 1/foobar; cp -lrv 1/* 2
`1/foobar' -> `2/foobar'
$ ls -i1 */foobar
1053003 1/foobar
1053003 2/foobar

$ mkdir a; echo quux > a/foobar
$ mv 1 3; rsync -avPhyH --del --link-dest=../2 a/ 3
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04

$ ls -i1 */foobar
1053003 2/foobar
1053007 3/foobar
1053006 a/foobar

$ mv 2 4; rsync -avPhyH --del --link-dest=../3 a/ 4
sending incremental file list
./
foobar
           5 100%    0.00kB/s    0:00:00 (xfer#1, to-check=0/2)

sent 105 bytes  received 34 bytes  278.00 bytes/sec
total size is 5  speedup is 0.04


$ ls -il1 */foobar
1053007 -rw-r--r-- 1 math math 5 Mar 30 00:57 3/foobar
1053008 -rw-r--r-- 1 math math 5 Mar 30 00:57 4/foobar
1053006 -rw-r--r-- 1 math math 5 Mar 30 00:57 a/foobar

$ md5sum [34a]/foobar
d3b07a382ec010c01889250fce66fb13  3/foobar
d3b07a382ec010c01889250fce66fb13  4/foobar
d3b07a382ec010c01889250fce66fb13  a/foobar

现在我们有两个备份a/foobar,它们在所有方面都相同,包括时间戳,但占用不同的索引节点。

人们可能会认为一种解决方案是--delete-before,它会消除增量扫描的好处,但这也没有帮助,因为文件不会被删除,而是用作可能进行增量复制的基础。

人们可能会进一步推测我们可以用 关闭这种增量复制对冲--whole-file,但这对算法没有任何帮助,没有办法得到我们想要的东西。

我认为这种行为是 rsync 中的另一个错误,可以通过仔细选择各种命令参数来解释有益的行为,但无法获得所需的结果。

不幸的是,解决方案将从作为原子操作的单个 rsync 转移到使用 进行空运行-n,记录它,处理该日志作为输入以手动预删除所有更改的文件,然后运行rsync --link-dest以获得我们想要的东西 - 这是一个很大的混乱与单个干净的 rsync 相比。

附录:尝试在对生产框进行备份之前在备份服务器上进行预链接$yesterday-但结果相同 -$todayrsync --link-dest=../$yesterday $yesterday/ $today任何以任何方式存在的文件,即使是 0 长度,也永远不会被删除和链接目标,而是将从 sourcedir 中使用新的 inode 制作一个全新的副本,并使用更多的磁盘空间。

寻找pax(1)一种可能的备份前预链接解决方案。

答案1

(从问题编辑转换而来)

通过升级rsync可以解决这个问题。 3.1.1 或更高版本现在将--link-dest使用一个硬链接文件替换目标和目录中的相同文件。节省大量空间。

相关内容