为什么 du 和 ls 报告的文件大小差异很大?

为什么 du 和 ls 报告的文件大小差异很大?

在服务器上,我有一个目录/opt/kafka/data/topics

$ du -hs /opt/kafka/data/topics
52M     /opt/kafka/data/topics

当我像这样 tar 这个目录时

$ tar czfv /tmp/topics.tar.gz /opt/kafka/data/topics

我得到了合理的文件大小

$ ls -alh /tmp/topics.tar.gz
-rw-r--r-- 1 user user  11M Jan 12 15:15 kafka

然而,当我下载topics.tar.gz到我的本地 OS X 电脑并解压时,它占用10GB!


/opt/kafka/data/topics仔细检查服务器上的内容后,我注意到ls其中包含许多 10MB 的文件:

$ find /opt/kafka/data -type f -exec ls -alh {} \;
... [output]
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
-rw-r--r-- 1 user user 10M Jan 12 02:45 /opt/kafka/data/topics/user-entities-KSTREAM-KEY-SELECT-0000000123-repartition-2/00000000000000000012.index
... [and many more]

du报告称这些 10MB 文件中每个都是 0 字节:

$ du -h /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index
0       /opt/kafka/data/topics/user-entities-KTABLE-REDUCE-STATE-STORE-0000000178-changelog-1/00000000000000000000.index

那么,到底发生了什么?显然我在这里遗漏了一些东西:

  • du报告总共 52M。这是有道理的,因为安装的设备/opt/kafka/data只有 5GB,df报告只使用了 2%,并且一切仍在运行。
  • tar将内容压缩到 10M。这也是有道理的。
  • ls报告称许多文件在磁盘上的大小为 10M,而当我提取档案时,我得到了 10GB。
  • du报告称这些相同的文件都是 0 字节。
  • mount报道称/dev/sdc on /opt/kafka/data type ext4 (rw,relatime,data=ordered)

什么都说不通。是否存在某种我不知道的透明磁盘压缩?

答案1

根据评论中的讨论,所有文件都很稀疏。这种事情实际上让很多人在第一次处理时感到困惑,所以不要感到难过。

ls和报告的值这里实际上发生了什么du

用一个例子就可以很容易地解释这一点。

假设您创建一个空文件,然后从头开始向其中写入 1MB 的数据。生成的文件大小为 1MB,占用 1MB 磁盘空间。ls和都du将报告该文件的相同大小 1MB。

现在假设你创建一个空文件,然后调用seek()将 1MB 移入文件,然后写入一个字节。生成的文件看起来长度为 1MB + 1 字节,但实际上其中只有 1 字节的数据。

在较旧的文件系统上,第二个文件需要花费很长时间才能写入 1 字节的数据,因为操作系统在写出最后 1 字节的实际数据之前会忙于写出 1MB 的空字节。

这种低效率(无论是在创建文件的时间方面,还是在磁盘上占用的空间方面)正是稀疏文件出现的原因。支持稀疏文件的操作系统(如所有现代 UNIX 系统)不会写出 1MB 的空字节,而是会在文件系统的元数据中注释 0-1MB 区域为空,然后只存储您写入的单个字节。因此,文件看起来是 1MB + 1 字节长,但在磁盘上它只占用 1 个字节。此外,当有人读取该文件时,操作系统注释为空的任何区域都只会读回为空字节(因此对于用户程序来说,它看起来与第一个文件没有什么不同)。

ls这就是和报告的值之间的差异的来源du。默认情况下,ls报告文件的表观大小(即,如果从第一个字节开始读取文件并一直读到最后,将读取多少数据),而du报告文件在磁盘上实际使用的空间(通常不包括操作系统执行的其他节省空间的技巧,如透明压缩)。 在这种情况下du同意因为只报告磁盘上实际物理使用的空间量。dfdf

通过将该ls -l命令更改为ls -ls,您将获得一个额外的列,显示文件的实际磁盘大小,该列应与 一致du

相关内容