为什么第一个 rsync 命令可以完美地创建 /tmp/data 到 /tmp/bak 的克隆使用硬链接但第二个创建了一个克隆复制字节而不是硬链接?
rsync -a --link-dest=/tmp/data /tmp/data/ /tmp/bak/ # HARDLINKS
rsync -a -R --link-dest=/tmp/data /tmp/data/ /tmp/bak/ # REGULAR COPIES
测试/重现的步骤
cd /tmp/
rm -rf data bak
mkdir data bak
echo foo > data/foo
stat /tmp/data/foo | grep Inode
rsync -a --link-dest=/tmp/data /tmp/data/ /tmp/bak/
stat /tmp/bak/foo | grep Inode
### Note that the inode is the same as above.
rm bak/*
rsync -a -R --link-dest=/tmp/data /tmp/data/ /tmp/bak/
stat /tmp/bak/tmp/data/foo | grep Inode
### Note that the inode is different.
答案1
使用-R
( --relative
) 标志时,所有路径都会以源路径为前缀,包括任何--link-dest
路径。
通过你的例子来解决这个问题,
rsync -a -R --link-dest=/tmp/data /tmp/data/ /tmp/bak/
这意味着链接目标路径变为/tmp/data/tmp/data
。 (您可以cp -al /tmp/data /tmp/link
使用 和 使用更清楚地看到这一点strace -f rsync ... --link-dest=/tmp/link
。)
本例中的解决方案是使用--link-dest=/
,以便生成的起点成为您想要的--link-dest=/tmp/data
rsync -a -R --link-dest=/ /tmp/data/ /tmp/bak/
stat /tmp/bak/tmp/data/foo | grep Inode # Same inode as source, with Links: 2
答案2
这是一个有趣的问题。
当您使用 时rsync -R
,它会将 复制tmp/data
到目标目录中。
问题是,当 rsync 复制时,它会首先检查文件是否存在于以下给出的目录中--link-dest
:
意思是,它将/tmp/bak/*
与进行比较/tmp/data/*
。
问题是,当您启动rsync -R
命令时,该foo
文件不会位于可以与 /tmp/data/ 进行比较来进行链接的位置,它将位于/tmp/bak/tmp/data/foo
,而 rsync 愚蠢地只会在以下情况下为其进行硬链接:它是给定目录的根(在该示例中为/tmp/data
和/tmp/bak
)。