当我总结文件的大小时,我得到了一个数字。如果我跑du
,我会得到另一个数字。如果我du
对分区上的所有文件运行,则它与所df
使用的声明不匹配。为什么我的文件总大小有这么多不同的数字?电脑不能添加吗?
说到添加:当我添加 的“已使用”和“可用”列时df
,我没有得到总数。这个总数小于我的分区的大小。如果我将分区大小相加,我就得不到磁盘大小!是什么赋予了?
答案1
将数字相加很容易。问题是,有许多不同的数字需要相加。
一个文件使用多少磁盘空间?
基本思想是一个包含n字节使用n字节的磁盘空间,加上一些控制信息:文件的元数据(权限、时间戳等),以及系统需要查找文件存储位置的信息的一点开销。然而,还有很多并发症。
微观并发症
将每个文件视为图书馆中的一系列书籍。较小的文件仅构成一卷,但较大的文件由许多卷组成,就像一本百科全书。为了能够找到文件,有一个引用每个卷的卡片目录。由于封面的原因,每卷都有一些开销。如果文件很小,这个开销就比较大。卡片目录本身也占用了一些空间。
更技术一点,在典型的简单文件系统中,空间被划分为块。典型的块大小为 4KiB。每个文件占用整数个块。除非文件大小是块大小的倍数,否则仅部分使用最后一个块。因此,1 字节文件和 4096 字节文件均占用 1 个块,而 4097 字节文件则占用 2 个块。您可以使用ls
或来观察这一点du
:如果您的文件系统具有 4KiB 块大小,则ls -s
和du
将报告 1 字节文件为 4KiB。
如果文件很大,则需要额外的块来存储组成文件的块列表(这些是间接块;更复杂的文件系统可以通过以下形式对此进行优化范围)。这些不会显示在ls -l
GNU 或 GNU报告的文件大小中du --apparent-size
。du
和ls -s
报告磁盘使用情况而不是大小,确实说明了这些问题。
一些文件系统尝试重用最后一个块中剩余的可用空间将多个文件尾部打包在同一个块中。一些文件系统(例如Linux 3.8 以后的 ext4对于完全适合 inode 的小文件(只有几个字节)使用 0 块。
宏观并发症
一般来说,如上所示,报告的总大小du
是文件使用的块或盘区大小的总和。
du
如果文件被压缩,则报告的大小可能会更小。 Unix 系统传统上支持粗略的压缩形式:如果文件块仅包含空字节,则文件系统可以完全忽略该块,而不是存储零块。像这样省略块的文件称为稀疏文件。当文件包含大量空字节时,不会自动创建稀疏文件,应用程序必须安排文件变得稀疏。
晚期并发症
zfs 和 btrfs 等非常现代的文件系统的两个主要功能使文件大小和磁盘使用之间的关系变得更加遥远:快照和重复数据删除。
快照是文件系统在特定日期的冻结状态。支持此功能的文件系统可以包含在不同日期拍摄的多个快照。当然,这些快照会占用空间。一种极端情况是,如果您从文件系统的活动版本中删除所有文件,如果还有剩余快照,文件系统不会变空。
自拍摄快照以来或在拍摄两个快照之间未更改的任何文件或块在快照和活动版本或其他快照中完全相同地存在。这是通过以下方式实现的写时复制。在某些边缘情况下,由于可用空间不足,删除整个文件系统上的文件可能会失败 - 因为删除该文件需要在目录中复制一个块,而即使是那个块也没有更多空间。
重复数据删除是一种存储优化技术,包括避免存储相同的块。对于典型数据,查找重复项并不总是值得付出努力。两个都兹夫斯和BTFS支持重复数据删除作为可选功能。
为什么总大小du
与文件大小的总和不同?
正如我们在上面看到的,每个文件报告的大小du
通常是文件使用的块或范围的大小之和。请注意,默认情况下,ls -l
以字节为单位列出大小,但du
在一些更传统的系统上以 KiB 或 512 字节单位(扇区)列出大小(du -k
强制使用千字节)。大多数现代 unices 支持ls -lh
并du -h
使用“人类可读”的数字,使用 K、M、G 等就足够了(对于 KiB、MiB、GiB)。
当您du
在目录上运行时,它会汇总目录树中所有文件的磁盘使用情况,包括目录他们自己。目录包含数据(文件的名称以及指向文件元数据所在位置的指针),因此它需要一些存储空间。小目录将占用一个块,较大的目录将需要更多块。目录使用的存储量有时不仅取决于它包含的文件,还取决于它们插入的顺序以及删除某些文件的顺序(对于某些文件系统,这可能会留下漏洞 - 磁盘空间和性能之间的折衷) ),但差异很小(到处都是额外的块)。当您运行时ls -ld /some/directory
,会列出目录的大小。 (请注意,输出顶部的“total NNN”行ls -l
是一个不相关的数字,它是列出的项目的块大小的总和,以 KiB 或扇区表示。)
请记住,其中du
包括点文件ls
除非您使用-A
or选项,否则不会显示-a
。
有时du
报告的金额少于预期金额。如果有的话就会发生这种情况硬链接在目录树内部:du
每个文件仅计数一次。使用du -l
switch 来统计文件数量氮次如果他们有氮硬链接。
在某些文件系统(例如ZFS
Linux)上,du
不报告文件的扩展属性占用的完整磁盘空间。
请注意,如果目录下有挂载点,du
除非给出选项,否则也会计算这些挂载点上的所有文件-x
。因此,如果您想要根文件系统中文件的总大小,请运行du -x /
,而不是du /
。
如果文件系统安装到非空目录,该目录中的文件被安装的文件系统隐藏。他们仍然占据着自己的空间,但du
找不到他们。
已删除的文件
当一个文件是已删除,这仅删除目录条目,不一定删除文件本身。要真正删除文件并回收其磁盘空间,需要满足两个条件:
- 文件的链接计数必须降至 0:如果文件有多个硬链接,删除一个不会影响其他文件。
- 只要文件被某个进程打开,数据就会保留。只有当所有进程都关闭该文件时,该文件才会被删除。输出
fuser -m
或者lsof
挂载点上包括在该文件系统上打开文件的进程,即使该文件已被删除。 - 即使没有进程打开已删除的文件,如果该文件是设备的后端,也可能无法回收该文件的空间
loop
。losetup -a
(如root
)可以告诉您loop
当前设置了哪些设备以及在什么文件上。losetup -d
在回收磁盘空间之前,必须销毁循环设备(使用)。
如果您在某些文件管理器或 GUI 环境中删除文件,它可能会被放入垃圾区域,并且可以在其中恢复删除。只要文件可以恢复,它的空间仍然会被消耗。
这些数字df
到底来自哪里?
典型的文件系统包含:
只报道了第一种du
。当涉及到时df
,“已使用”、“可用”和总列中的内容取决于文件系统(当然,已使用的块(包括间接块)始终位于“已使用”列中,未使用的块始终位于“可用”栏)。
ext2/ext3/ext4 中的文件系统预订5%的空间给root用户。这对于根文件系统很有用,可以在系统已满时保持系统继续运行(特别是对于日志记录,并让系统管理员在解决问题时存储一些数据)。即使对于诸如 之类的数据分区/home
,保留保留空间也是有用的,因为几乎已满的文件系统很容易产生碎片。 Linux 试图通过在写入文件时预先分配许多连续块来避免碎片(这会减慢文件访问速度,尤其是在硬盘等旋转机械设备上),但如果连续块不多,那就无法工作。
传统文件系统(包括 ext4 但不包括 btrfs)保留固定数量的文件系统索引节点创建文件系统时。这显着简化了文件系统的设计,但缺点是需要适当调整 inode 的数量:inode 太多,会浪费空间;如果 inode 太少,文件系统可能会在空间耗尽之前耗尽 inode。该命令df -i
报告有多少 inode 正在使用中以及有多少 inode 可用(该概念不适用的文件系统可能会报告 0)。
在包含 ext2/ext3/ext4 文件系统的卷上运行tune2fs -l
会报告一些统计信息,包括总数以及空闲 inode 和块的数量。
另一个可能混淆物质的特征是子卷(支持于BTFS,并在 zfs 中的名称下数据集)。多个子卷共享相同的空间,但具有单独的目录树根。
如果文件系统通过网络(NFS、Samba 等)安装,并且服务器导出该文件系统的一部分(例如服务器有一个/home
文件系统,并导出/home/bob
),然后df
在客户端上反映整个文件系统的数据,而不仅仅是导出并安装在客户端上的部分的数据。
我的磁盘空间被用来做什么?
正如我们在上面看到的,报告的总大小df
并不总是考虑文件系统的所有控制数据。如果需要,使用特定于文件系统的工具来获取文件系统的确切大小。例如,对于 ext2/ext3/ext4,运行tune2fs -l
并将块大小乘以块计数。
创建文件系统时,它通常会填满封闭分区或卷上的可用空间。有时,当您移动文件系统或调整卷大小时,您最终可能会得到较小的文件系统。
在 Linux 上,lsblk
提供了可用存储卷的良好概述。如需更多信息,或者如果您没有lsblk
,请使用专门的卷管理或分区工具来检查您拥有哪些分区。在 Linux 上,有lvs
, vgs
,pvs
代表左心室容量,fdisk
对于传统的 PC 风格(“MBR”)分区(以及最新系统上的 GPT),gdisk
为了GPT分区,disklabel
对于 BSD 磁盘标签,分手了等Linux下,cat /proc/partitions
简单总结一下。典型的安装至少有两个操作系统使用的分区或卷:一个文件系统(有时更多)和一个交换体积。
有些计算机有一个分区,其中包含BIOS或其他诊断软件。计算机具有UEFI有一个专用的引导加载程序分区。
最后,请注意,大多数计算机程序使用基于 1024 = 2 10的幂的单位(因为程序员喜欢二进制和 2 的幂)。所以 1 kB = 1024 B,1 MB = 1048576 B,1 GB = 1073741824,1 TB = 1099511627776 B,......正式地,这些单位被称为千比字节基布,兆比字节MiB等,但大多数软件仅报告k或kB、M或MB等。另一方面,硬盘制造商系统地使用公制(基于1000的单位)。因此,1 TB 驱动器仅为 931 GiB 或 0.904 TiB。
答案2
计算文件大小和磁盘空间的复杂性的简短摘要:
文件在磁盘上占用的空间是它占用的块数乘以每个块的大小+它占用的索引节点数。一个 1 字节长的文件至少需要 1 个块、1 个 inode 和 1 个目录项。
但如果该文件是到另一个文件的硬链接,则可能只需要 1 个额外的目录条目。这只是对同一组块的另一个引用。
- 文件内容的大小。这就是
ls
显示的内容。 - 可用磁盘空间不是您可以容纳的最大文件的大小,也不是磁盘上适合的所有文件内容大小的总和。它介于两者之间。它取决于文件数量(占用索引节点)、块大小以及每个文件的内容完全填充块的程度。
这只是文件系统的皮毛,而且过于简单化了。还要记住,不同的文件系统的操作方式不同。
stat
对于发现其中一些信息非常有帮助。以下是如何使用 stat 及其用途的一些示例:http://landoflinux.com/linux_stat_command_examples.html
答案3
df
通常用于查看文件系统是什么、每个文件系统有多满以及它们安装在哪里。当您的文件系统空间不足,并且可能想要在文件系统之间转移内容或购买更大的磁盘等时,这非常有用。
du
显示每个目录消耗的累积存储量的详细信息(有点像windirstat
Windows 中)。非常适合在尝试进行文件清理时查找占用空间的位置。
除了其他人解释的微小数字差异外,我认为du
和df
实用程序的目的非常不同。
答案4
du
我将在这里说明导致与 不同的不同情况df
。
df
计算文件系统分配的块数,du
使用每个文件的大小信息。差异可能有多种原因:
应用程序仍打开的未链接(已删除)的文件。文件信息丢失,块仍然分配。
lsof +aL1 <filesystem>
将帮助您识别流程。大多数时候,您必须终止进程以释放空间(这取决于进程,有时重新加载配置就足够了)。挂载点下的文件隐藏到
du
但不隐藏到df
。debugfs
可以帮助你读取文件系统。$ sudo debugfs debugfs 1.42.12 (29-Aug-2014) debugfs: open /dev/xxx (the desired file system device) debugfs: cd /boot debugfs: ls -l 1966081 40755 (2) 0 0 4096 26-May-2016 16:28 . 2 40555 (2) 0 0 4096 11-May-2016 10:43 .. 1974291 100644 (1) 0 0 0 26-May-2016 16:28 bob <---<<< /boot/bob is hidden by /boot fs
稀疏文件看起来比实际更大。未分配的块不计入,
df
但表观文件大小计入du
。
请注意,硬链接不会欺骗du
。