使用 rsync 复制数据会导致大小差异

car*_*ing 4 linux ext4 rsync opensuse

我正在切换机器,并将旧硬盘 ( /dev/sda4) 连接到新机器。

720G与新机器 ( ) 相比,旧机器的硬盘驱动器 ( ) 稍小736G,因此我也创建了一个稍大的分区。

于是,我接着跑去rsync将所有数据复制到新分区,如下图:

linux-70e2:/ # time rsync -azprvl /mnt/external-disk/foo /media/sda4/

...
sent 169,237,139,987 bytes  received 24,529 bytes  24,419,185.41 bytes/sec
total size is 190,542,953,489  speedup is 1.13

real    115m30.297s
user    112m13.068s
sys     3m59.996s
Run Code Online (Sandbox Code Playgroud)

数据被复制且没有错误。

但是,当我这样做时:

du -h -m -s /mnt/external-disk/foo /media/sda4/foo
Run Code Online (Sandbox Code Playgroud)

我得到:

162414  /mnt/external-disk/foo
181721  /media/sda4/foo
Run Code Online (Sandbox Code Playgroud)

有人可以解释一下这种巨大的差异吗?为什么我没有得到相同的结果?这几天让我发疯。还有一些其他分区,我也遇到了类似的差异。

两个分区都是ext4.

linux-70e2:/ # mount | grep sda4
/dev/nvme0n1p5 on /media/sda4 type ext4 (rw,relatime,data=ordered)
/dev/sda4 on /mnt/external-disk type ext4 (rw,nosuid,nodev,relatime,data=ordered,uhelper=udisks2)
Run Code Online (Sandbox Code Playgroud)

据我所知,这两个 SSD 驱动器都没有问题。其中之一是全新的。我e2fsck两个都跑过。

另外,我跑了:

find -L /mnt/external-disk type/foo -type l
Run Code Online (Sandbox Code Playgroud)

并且这不会在源目录下列出任何符号链接。

这不是我第一次使用rsync这种东西,但我以前从未遇到过这种问题。请指教!

sho*_*hok 6

这种差异很可能是由于旧磁盘上的文件稀疏造成的。

无论如何,我们首先检查文件和索引节点号是否相同:

  • find <path> | wc -l两个安装点上的问题。文件/目录的数量是否相同?
  • 问题df -i。inode的数量是否相同?

如果两个问题的答案都是肯定的,则差异可以通过新磁盘上的文件更加稀疏来解释。但什么是稀疏文件呢?简而言之,稀疏文件是比看起来更小的普通文件。这是可能的,要归功于(相对)现代文件系统的一个功能,该功能不是将所有零写入文件,而是简单地设置一个标志告诉系统“这个文件(或部分)充满了零,不要让我写商场”。

默认情况下,du报告文件占用的实际空间,而不是表观大小。要显示外观尺寸,请使用du --apparent-size(有关其他选项,请参阅du 手册页

作为一个实际示例,您可以使用命令创建稀疏文件truncate test.img -s 1G。据 报道ls,新创建的文件大小为 1 GB,但如果您尝试du -hs test.img,您会看到一个非常非常小的文件大小(甚至可能为零!)。怎么可能呢?如上所述,现代文件系统有时会对应用程序“撒谎”,报告实际不存在的分配大小。另一面du -hs --apparent-size test.img将打印与 相同的尺寸ls

当您开始写入稀疏文件时,文件系统将动态分配所需的空间。例如,发布会dd if=/etc/services of=test.img conv=notrunc,nocreat将一些数据写入之前全稀疏的test.img文件中。现在,运行du -hs test.img将报告分配给数据存储的约 600 KB。

一个明显但非常重要的含义是稀疏文件支持只能针对零填充文件(或部分)进行优化。在写入文件的同一时刻,其分配的空间开始增长。如果您向文件写入其他零,则这是真实事件,除非应用程序知道如何处理稀疏文件(在这种情况下,应用程序将通知文件系统它将写入所有零,并且文件系统相应地进行优化)。

如果您想真正预分配一些空间怎么办?然后你就可以使用fallocate test.img -l 1G. 如果执行ls; du -hs test.img; du -hs --apparent-size test.img,您将看到所有工具报告的大小完全相同,因为文件实际上已由调用完全分配fallocate

简而言之,在复制过程中,某些文件可能以不太稀疏的方式重新创建,用“真正的”零替换稀疏部分。要使用稀疏文件,rsync您必须使用该-S选项。