有人可能认为--link-dest
对相同的文件进行处理在所有情况下都有效。但是当文件存在时它不会,即使文件已过期/具有不同的内容。
正因为如此,从 rsync 手册页上--link-dest
:
“当复制到空的目标层次结构时,此选项效果最佳,因为 rsync 将现有文件视为明确的(因此,当目标文件已存在时,rsync 永远不会在链接目标目录中查找)”
这意味着,如果y/file
存在与源相同,并且z/file
已过时,
rsync -a --del -link-dest=y source:/file z
Run Code Online (Sandbox Code Playgroud)
将导致使用两个 inode(和两倍的磁盘空间),y/file
并且z/file
,它们将具有相同的内容和日期戳。
我遇到了这个,因为我基本上每天运行一次这个脚本来做每日备份:
mv $somedaysago $today;
yest=$today; today=`date +%Y%m%d`;
rsync -avPShyH --del --link-dest=../$yest host:/dirs $today
Run Code Online (Sandbox Code Playgroud)
因为我的备份跨越多达 10M 个文件,所以这样做rm -rf $olddir; rsync source:$dir newdir
会花费太长时间(特别是当每天只有 0.5% 的文件更改时,导致删除和创建 10M 目录条目只是为了处理 50K 新文件或更改文件,这将使我的次日未及时完成备份)。
这是情况的演示:
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
Run Code Online (Sandbox Code Playgroud)
现在我们有 2 个a/foobar
在所有方面都相同的备份,包括时间戳,但占用不同的 inode。
有人可能认为一种解决方案是--delete-before
,这会扼杀增量扫描的好处,但这也无济于事,因为文件不会被删除,而是用作增量复制可能的基础。
人们可能会进一步猜测,然后我们可以使用 关闭这种增量复制对冲--whole-file
,但这对算法没有任何帮助,无法获得我们想要的东西。
我认为这种行为是 rsync 中的另一个错误,其中可以通过仔细选择各种命令参数来解释有益的行为,但无法获得所需的结果。
不幸的是,一个解决方案是从作为原子操作的单个 rsync 移动到使用 的干运行-n
,记录它,将该日志作为输入处理以手动预删除所有更改的文件,然后运行rsync --link-dest
以获得我们想要的 - 一个大杂烩与单个干净的 rsync 相比。
附录:尝试在对生产盒进行备份之前在备份服务器上预链接$yesterday
和- 但相同的结果 -任何以任何方式存在的文件,即使是 0 长度,都不会被删除和链接目标,而是一个整体将使用新的 inode 从 sourcedir 制作新副本并使用更多磁盘空间。$today
rsync --link-dest=../$yesterday $yesterday/ $today
将其pax(1)
视为可能的备份前预链接解决方案。