阅读视图

发现新文章,点击刷新页面。
🔲 ☆

Linux上df和du统计磁盘占用大小差异分析

在 Linux 系统上,df 和 du 命令统计结果不一致是经常遇到的情况,其背后的原理涉及到文件系统如何管理磁盘空间和文件这两个不同的视角。

简单来说,核心差异在于:

  • df 报告的是文件系统级别的磁盘块使用情况,它查看的是磁盘块的分配情况。

  • du 报告的是文件级别的磁盘块使用情况,它通过累加每个文件的大小来计算。


1. 命令定义与工作原理

df (Disk Free)

  • 工作原理df 命令直接读取文件系统的超级块(Superblock) 中的信息。超级块中存储了整个文件系统的元数据,包括总空间、已用空间、空闲空间、inode 数量等。因此,df 的执行速度非常快,因为它不需要遍历所有目录和文件。

  • 它统计什么:文件系统上所有已分配的磁盘块(包括被文件占用的和部分被保留的)。

du (Disk Usage)

  • 工作原理du 命令会递归地遍历指定目录下的每一个文件和子目录,然后累加每个文件占用的磁盘空间大小。它的结果基于当前用户权限下能看到的文件。

  • 它统计什么:所有文件实际占用的磁盘块的总和。


2. 导致差异的常见原因分析

正是因为上述不同的工作原理,导致了以下几种常见的不一致情况:

原因一:文件被删除但未被释放(最常见!)

这是导致 df 显示空间已用而 du 找不到对应文件的最主要原因。

  • 原理:当一个文件正在被某个进程使用时,如果它被删除(rm),Linux 并不会立即释放其占用的磁盘空间。该进程仍然持有该文件的句柄,可以继续读写它。此时,该文件在目录中的条目(entry)消失了,所以 du 无法统计到它。但该文件占用的磁盘块在文件系统中仍然被标记为“已使用”,直到所有打开它的进程都关闭该文件后,空间才会被释放。

  • 表现df 显示磁盘使用率很高,但 du -sh / 统计根目录占用的总空间却小很多。

  • 解决方法

  1. 使用 lsof | grep deleted 命令查找已被删除但仍被进程打开的文件及其进程ID(PID)。

  2. 确认无误后,重启或终止相关进程(kill -9 <PID>),空间便会释放。

原因二:文件系统保留空间(Reserved Blocks)

  • 原理:默认情况下,Ext3/Ext4 等文件系统会保留约 5% 的磁盘空间(可由 tune2fs 调整)给 root 用户。这样做的目的是在磁盘空间写满时,为 root 用户保留一定的操作空间(例如执行必要的恢复命令),防止系统完全崩溃。

  • 表现df 会把这 5% 的保留空间计入“已用”空间,因为它对普通用户不可用。而 du 不会统计这部分空间,因为它不是被任何文件占用的。

  • 计算:对于一个 100G 的分区,df 可能会显示 95G 可用,5G 已用(其中一部分就是保留空间),即使一个文件都没存。

原因三:挂载点与其他文件系统

  • 原理:如果在 /data 目录下挂载了另一个磁盘(例如 /dev/sdb1),那么:

    • du -sh /data 会统计挂载在 /data 上的文件系统(/dev/sdb1)中所有文件的大小。

    • df /data 显示的是 /dev/sdb1 这个独立文件系统的使用情况。

    • 通常这里是一致的,但如果 /data 目录本身在根分区(/)中有一些文件(在挂载前存在的),这些文件会被挂载操作“隐藏”。du 看不到它们(因为访问路径被挂载点覆盖了),而 df 统计的是两个不同的文件系统,所以不会产生混淆。

原因四:稀疏文件(Sparse Files)

  • 原理:稀疏文件是一种特殊文件,它允许在文件中存在“空洞”(大量连续的0字节)。应用程序(如虚拟机磁盘镜像)创建它时,文件系统不会为这些空洞分配实际的磁盘块。

  • 表现

    • ls -l 或 du --apparent-size 显示的是文件的逻辑大小,会非常大。

    • du(默认行为)显示的是文件实际占用的磁盘块大小,会小很多。

    • df 反映的是文件系统实际消耗的磁盘块,与 du 的默认行为一致。

  • 示例:一个 100GB 的虚拟机磁盘文件,可能只实际占用 10GB 空间。du -h file 显示 10G,而 ls -lh file 显示 100G

原因五:文件系统元数据(Metadata)

  • 原理:文件系统自身需要消耗磁盘空间来存储元数据,如 inode 表、磁盘位图、日志文件(对于日志文件系统如 ext3/4, xfs)等。

  • 表现:这部分空间被文件系统占用,但不对应任何用户文件。因此 df 会将其统计为“已用空间”,而 du 根本无法统计这些元数据,从而导致 df 的结果略大于 du


总结与对比

特性dfdu
数据源文件系统超级块(元数据)递归遍历统计文件
统计视角磁盘块分配情况文件数据占用情况
速度非常快(直接读元数据)相对慢(需要遍历文件树)
包含保留空间
包含被删除但未释放的文件
包含稀疏文件“空洞”(只算实际块)(只算实际块,但 --apparent-size 算)
包含元数据(元数据也占用块)

实践建议

当遇到磁盘空间不足报警,但 du 找不到大文件时,排查思路如下:

  1. 首先执行 df -h,确认哪个分区使用率高。

  2. 然后执行 du -sh /path/to/mountpoint,查看该分区下文件总大小是否与 df 结果近似。

  3. 如果差异很大,首要怀疑有文件被删除未释放:使用 lsof +L1 或 lsof | grep deleted 命令检查。

  4. 其次考虑是否有隐藏挂载点、稀疏文件等原因。


云盘扩容后扩展分区操作

云主机的云盘从控制台100G扩容到300G后,根目录 /dev/vda1 显示还是100G,这通常是因为云盘扩容后只增加了底层存储空间,操作系统内部的分区和文件系统还未扩展。云平台的控制台扩容只是扩大了"物理磁盘"的容量,后续还需要在系统内部进行分区和文件系统的扩展。

1.确认底层磁盘容量
在操作系统内执行 lsblk 命令-4-5,它可以查看磁盘本身和分区的真实容量。

如果 lsblk 显示 /dev/vda 本身已经是300G,而其下的分区 /dev/vda1 还是100G,这就证实了是分区没有扩展-1-8

2.扩展分区
确认是分区问题后,需要扩展分区以填满磁盘的可用空间。推荐使用 growpart 工具-5,它能够自动调整分区大小。

growpart /dev/vda 1

注意:命令中 vda 和 1 之间的逗号后有一个空格-5。完成后,再次运行 lsblk 检查,此时 /dev/vda1 的大小应该显示为300G左右。

3.扩展文件系统
分区扩展后,最后一步是扩展文件系统,这样才能让操作系统真正使用新增的空间。需要根据文件系统类型选择相应的命令。

  • 如果文件系统是 ext4(常见于CentOS、Ubuntu等):

resize2fs /dev/vda1
  • 如果文件系统是 XFS(常见于较新版本的CentOS、RHEL):

xfs_growfs /

注意:对于XFS文件系统,需要指定挂载点(此处根目录为 /),而不是设备名。

重要提醒与建议

在进行任何磁盘操作前,请务必注意以下几点:

  • 备份数据:在对磁盘分区和文件系统进行操作前,强烈建议通过云平台创建快照备份数据-1-4,以防操作失误导致数据丢失。

  • 理解步骤:云盘扩容是一个多步骤的过程,控制台扩容后,必须登陆系统完成分区和文件系统的扩展,缺一不可-1-10

  • 命令匹配:务必确保扩展文件系统的命令与系统上的文件系统类型匹配,否则可能报错或无效-5


参考:

🔲 ☆

MacOS格式化 U 盘

最近工作需要买了个64G的U盘,在Windows系统下使用格式化了 NTFS 格式,但是在Mac上无法写入,macOS默认仅支持读取NTFS,还得再格一次,真是格老子的了。

Mac 上“磁盘工具”中可用的文件系统格式

Mac 上的“磁盘工具”支持多种文件系统格式:

  • Apple 文件系统 (APFS):macOS 10.13 或后续版本使用的文件系统。

  • Mac OS 扩展:macOS 10.12 或之前版本使用的文件系统。

  • MS-DOS (FAT) 和 ExFAT:与 Windows 兼容的文件系统。

Windows 兼容格式

如果格式化磁盘以配合 Windows 使用,请选取以下其中一种兼容 Windows 的文件系统格式。

  • MS-DOS (FAT):用于 Windows 宗卷且大小为 32 GB 或不足 32 GB。

  • ExFAT:用于 Windows 宗卷且大小超过 32 GB。

文件系统选择

1755783615947231.png


MacOS 使用终端格式化 U 盘

在面对无法清除U盘分区,无法写入,无法抹掉情况时,在 Mac 上可以使用终端彻底格式化 U 盘,可以使用 diskutil 命令。以下是详细步骤:

⚠️ 注意事项

  • 格式化会清空 U 盘上的所有数据,请先备份重要文件。

  • 确保选择了正确的 U 盘,否则可能误删其他数据。

1、打开终端查看 U 盘信息

输入以下命令查看所有磁盘设备:

diskutil list

2、卸载 U 盘

格式化前,先卸载 U 盘:

diskutil umountDisk /dev/disk4

3、覆盖 U 盘(可选)

diskutil zeroDisk /dev/disk4

4、彻底格式化 U 盘

格式化并抹除 U 盘,使用以下命令:

diskutil eraseDisk FAT32 USB_NAME MBRFormat /dev/disk4
  • FAT32 —— 兼容 Windows 和 macOS(可改为 ExFATAPFS)。

  • USB_NAME —— 你想给 U 盘起的名字(可替换为你喜欢的)。

  • MBRFormat —— 使用主引导记录 (MBR),适用于 U 盘。

  • /dev/disk4 —— 确保这里是你的 U 盘编号!

完整操作示例:

> diskutil list
/dev/disk0 (internal, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *500.3 GB   disk0
   1:             Apple_APFS_ISC Container disk1         524.3 MB   disk0s1
   2:                 Apple_APFS Container disk3         494.4 GB   disk0s2
   3:        Apple_APFS_Recovery Container disk2         5.4 GB     disk0s3

/dev/disk3 (synthesized):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      APFS Container Scheme -                      +494.4 GB   disk3
                                 Physical Store disk0s2
   1:                APFS Volume MacintoshHD - Data      365.9 GB   disk3s1
   2:                APFS Volume MacintoshHD             10.2 GB    disk3s3
   3:              APFS Snapshot com.apple.os.update-... 10.2 GB    disk3s3s1
   4:                APFS Volume Preboot                 6.1 GB     disk3s4
   5:                APFS Volume Recovery                933.9 MB   disk3s5
   6:                APFS Volume VM                      20.5 KB    disk3s6

/dev/disk4 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *62.9 GB    disk4
   1:               Windows_NTFS                         62.9 GB    disk4s1

> diskutil unmountDisk /dev/disk4
Unmount of all volumes on disk4 was successful

> diskutil eraseDisk FAT32 USB_NAME MBRFormat /dev/disk4
Started erase on disk4
Unmounting disk
Creating the partition map
Waiting for partitions to activate
Formatting disk4s1 as MS-DOS (FAT32) with name USB_NAME
512 bytes per physical sector
/dev/rdisk4s1: 122847872 sectors in 1919498 FAT32 clusters (32768 bytes/cluster)
bps=512 spc=64 res=32 nft=2 mid=0xf8 spt=32 hds=255 hid=2048 drv=0x80 bsec=122877952 bspf=14997 rdcl=2 infs=1 bkbs=6
Mounting disk
Finished erase on disk4

示例中U 盘的 IDENTIFIER 是 disk4(你的可能不同)。

如果要使用 ExFAT 格式(支持大文件,兼容性好):

diskutil eraseDisk ExFAT USB_NAME MBRFormat /dev/disk4

如果要格式化为 macOS 专用格式 (APFS)

diskutil eraseDisk APFS USB_NAME GPT /dev/disk4

5、安全擦除(可选)

如果要彻底清除数据,使其难以恢复,可以用 secureErase

diskutil secureErase 2 /dev/disk4

参数解释:

  • 0 – 快速擦除(不安全)。

  • 1 – 单次写入 0。

  • 2 – (推荐) 7 次写入随机数据。

  • 3 – 35 次写入随机数据(极端安全)。

6、弹出 U 盘

格式化完成后,可以安全弹出:

diskutil eject /dev/disk4

然后拔掉 U 盘即可。

格式化 U 盘命令操作顺序

  1. diskutil list → 找到 U 盘的编号。

  2. diskutil unmountDisk /dev/diskX → 卸载 U 盘。

  3. diskutil zeroDisk /dev/diskX → 覆盖 U 盘。(可选)

  4. diskutil eraseDisk FORMAT USB_NAME MBRFormat /dev/diskX → 彻底格式化。

  5. diskutil secureErase ARGS /dev/diskX → 安全擦除数据。(可选)

  6. diskutil eject /dev/diskX → 安全弹出 U 盘。


MacOS 使用“磁盘工具”格式化 U 盘

在“磁盘工具”中,可以格式化可用在基于 Microsoft Windows 的电脑以及 Mac 的外置磁盘。

【警告】格式化磁盘或宗卷会抹掉其中的所有文件。格式化之前,请将需要的任何文件存储到另一个宗卷。

  1. 在 Mac 上的“磁盘工具” App  中,选取“显示”>“显示所有设备”。

    如果“磁盘工具”未打开,请点按程序坞中的“启动台”图标 ,在搜索栏中键入“磁盘工具”,然后点按“磁盘工具”图标 

  2. 在边栏中,选择要格式化以用于 Windows 电脑的磁盘。disk1.png

  3. 点按工具栏中的“抹掉”按钮 

  4. 在“抹掉”对话框中,点按“方案”弹出式菜单,然后选取一种分区方案disk2.png

  5. 点按“格式”弹出式菜单,然后选取以下一项:

  • MS-DOS (FAT):如果磁盘大小不超过 32 GB,请选取此格式。

  • ExFAT:如果磁盘大小超过 32 GB,请选取此格式。

  • 输入宗卷的名称。

    宗卷名称的最大长度为 11 个字符。

  • 点按“抹掉”,然后点按“完成”。disk3.pngdisk4.png


  • 参考:

    🔲 ⭐

    Linux系统下查看硬盘转速


    1740661422600414.png


    在Linux系统中,了解硬盘的转速对于评估系统性能和进行硬件优化具有重要意义,硬盘转速通常以每分钟转数(RPM, Revolutions Per Minute)来衡量,是影响数据传输速度的关键因素之一。以下是不同转速硬盘(包括7200rpm、10000rpm和15000rpm)在关键性能指标上的对比表:

    硬盘转速读写速度平均寻道时间数据传输率故障率适用场景
    7200rpm中等较长较低较高一般办公、家庭娱乐
    10000rpm较快较短较高中等企业级应用、轻量级数据库
    15000rpm极快极短极高较低高性能计算、数据中心、虚拟化环境

    使用hdparm命令查看硬盘转速

    hdparm是一个常用的硬盘参数设置工具,可以用于显示硬盘的各种信息,包括转速,以下是使用hdparm命令查看硬盘转速的方法:

    1、安装hdparm

    大多数Linux发行版默认都安装了hdparm,如果没有安装,可以使用以下命令进行安装:

       sudo apt-get install hdparm  # Debian/Ubuntu系统
       sudo yum install hdparm      # CentOS/RHEL系统

    2、查看硬盘转速

    使用以下命令查看硬盘的转速:

       sudo hdparm -I /dev/sda | grep Rotation

    /dev/sda是你要查看的硬盘设备路径,根据实际情况替换为相应的设备名称,如果你要查看的设备是/dev/sdb,则命令为:

       sudo hdparm -I /dev/sdb | grep Rotation

    3、输出结果解释

    命令执行后,会输出类似如下的信息:

       Nominal media rotation rate: 7200

    这里的7200表示硬盘的转速为7200 RPM。如果是固态硬盘(SSD),输出可能是 Rotation Rate: Solid State Device。

    使用smartctl命令查看硬盘转速

    smartctl是一个用于读取硬盘S.M.A.R.T.(Self-Monitoring, Analysis and Reporting Technology)信息的工具,也可以用于查看硬盘的转速,以下是使用smartctl命令查看硬盘转速的方法:

    1、安装smartmontools

    smartctlsmartmontools软件包的一部分,首先需要安装这个软件包:

       sudo apt-get install smartmontools  # Debian/Ubuntu系统
       sudo yum install smartmontools      # CentOS/RHEL系统

    2、查看硬盘转速

    使用以下命令查看硬盘的转速:

       sudo smartctl -a /dev/sda | grep Rotation

    同样,将/dev/sda替换为你实际要查看的设备名称。

    3、输出结果解释

    命令执行后,会输出类似如下的信息:

       Rotation Rate: 7200 rpm

    这里的7200 rpm表示硬盘的转速为7200 RPM。

    其他方法

    除了上述两种常用方法外,还有其他一些方法可以查看硬盘的转速或相关信息:

    使用lsblk命令:虽然lsblk不会直接显示硬盘转速,但它可以提供硬盘的型号和供应商信息,根据这些信息可以进一步查找硬盘的转速。

      lsblk -d -o NAME,ROTA,SIZE,MODEL

    ROTA 列显示设备是否为旋转设备(1 表示机械硬盘,0 表示固态硬盘)。

    查看sys文件系统:通过查看/sys文件系统中的相应设备文件,可以获取硬盘是否为旋转设备的信息。

      cat /sys/block/sda/queue/rotational

    如果输出为1,则表示该设备是旋转设备;如果输出为0,则表示该设备是固态硬盘。

    在Linux系统中,有多种方法可以查看硬盘的转速,其中最常用的是hdparmsmartctl命令,这些命令不仅可以显示硬盘的转速,还可以提供其他有用的硬盘信息,帮助用户更好地了解和管理自己的硬件设备,选择合适的方法并根据实际需求进行操作,可以有效地提升系统性能和稳定性。


    参考:

    ❌