ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

Linux磁盘空间排查:深入理解du与df差异及实战应用

Linux磁盘空间排查:深入理解du与df差异及实战应用 1. 从一次磁盘告警说起为什么du比df更值得信赖那天下午监控系统突然弹出一条告警“服务器/home分区磁盘使用率超过 90%”。我第一反应是执行df -h结果确实显示使用率高达 95%。按照常规思路我登录服务器准备清理一些日志或临时文件。然而当我用du -sh /home去统计/home目录的实际大小时却发现结果和df显示的差了将近 30GB。这“消失”的 30GB 空间去哪了是du算错了还是df在骗我这个看似简单的磁盘空间问题背后其实牵扯到 Linux 文件系统一个非常核心但容易被忽略的机制已删除但未释放的文件。对于很多刚接触 Linux 系统管理的朋友甚至一些有经验的开发者dudisk usage和dfdisk free这两个命令常常被混用或者只知其然不知其所以然。df告诉你文件系统层面的空间使用情况而du则从文件层级统计空间占用。当两者数据对不上时往往就是问题所在。网络上热词“centos du df 磁盘空间差太多”就是这种困惑的集中体现。本文将深入du命令的骨髓不仅告诉你每个参数怎么用更会结合文件系统原理、常见生产环境问题让你彻底搞懂磁盘空间那点事成为一个能精准定位空间问题的“空间侦探”。2.du命令的核心原理与df的本质区别要玩转du首先必须理解它和df的根本不同。这不仅仅是两个命令的差异更是两种统计视角的碰撞。2.1df文件系统块级别的“上帝视角”df命令查看的是**文件系统如 ext4, xfs**的磁盘空间信息。它的数据直接来源于文件系统的超级块superblock。你可以把文件系统想象成一个巨大的仓库仓库被划分成许多固定大小的“块”block通常是 4KB。df汇报的是这个仓库总共有多少块已经分配使用了多少块还剩多少块空闲。它的计算非常直接已用空间 总块数 - 空闲块数 * 块大小。这里有个关键点即使一个文件只写了 1 个字节它也会独占至少一个完整的块。这就是“块大小”对空间使用的影响。2.2du文件层级遍历的“会计视角”与df的宏观统计不同du命令的工作方式是遍历指定目录下的所有文件和子目录然后累加每个文件实际占用的磁盘空间。这个“实际占用”通常指的是文件使用的块数乘以块大小。这里就引出了两个核心概念逻辑大小 vs 物理大小一个文本文件内容只有 “hello”5字节这是它的逻辑大小。但在磁盘上它可能占用了一个 4KB 的块这就是它的物理大小。du默认报告的是物理大小--apparent-size参数可以看逻辑大小。硬链接Hard Link的统计这是导致du统计“偏大”的一个常见原因。硬链接是同一个文件数据inode的多个路径入口。du在遍历时会为每一个硬链接都累加一次该文件的大小。如果同一个文件有 10 个硬链接du就会把它算 10 次。而df从块分配角度看只算一份。所以在存在大量硬链接的目录如/usr下的某些库文件du总和可能远大于df显示的使用量。2.3 经典矛盾du与df结果不一致的三大元凶回到开头的案例为什么数据对不上主要有以下三个原因已删除但未关闭的文件Deleted but not released这是生产环境最常见的“幽灵空间”杀手。当一个进程打开了一个文件例如一个正在写入的日志文件此时即使你用rm命令删除了这个文件只要进程没有关闭该文件的句柄该文件所占用的磁盘块就不会被释放。从df视角看这些块依然被占用但从du视角看因为文件路径已经消失遍历时找不到这个文件所以不会统计它。这就会导致df显示的使用率很高而du统计的目录大小却很小。可以使用lsof | grep deleted命令来查找这类“幽灵文件”。文件系统预留空间Reserved Blocks默认情况下ext3/ext4 文件系统会为 root 用户保留 5% 的磁盘空间对于 xfs也有类似机制。这部分空间是为了防止普通用户写满磁盘导致系统关键服务如 root 写日志崩溃。df命令会将这块预留空间计入“已用空间”而du自然不会去统计这块不属于任何文件的空间。容器与虚拟化的影响在 Docker、LXC 等容器环境下或者使用mount --bind绑定了目录时可能会产生更复杂的空间视图重叠需要结合df -i查看 inode 使用和du进行综合判断。提示当发现df和du差异巨大时第一个排查动作应该是lsof -n | grep deleted这能解决八成以上的“磁盘空间神秘消失”问题。3.du命令的实战语法与关键参数精讲掌握了原理我们再来细致拆解du这个工具本身。它的基础语法是du [选项] [文件或目录]。下面我们针对高频和易错参数进行深度解析。3.1 基础输出理解默认行为不带任何参数运行du [目录]它会递归列出该目录下每一个子目录的磁盘使用情况单位是 KB。输出可能非常冗长。du /var/log这个命令会从/var/log开始列出其下所有目录的占用最后一行是/var/log的总计。对于快速查看这并不友好。3.2 核心参数让输出变得高效有用-h(或--human-readable): 这是最常用的参数没有之一。它会将大小转换为人类易读的单位K, M, G, T。du -h /home-s(或--summarize):另一个最常用参数。它只显示指定目录的总计大小而不列出其内部细节。-s和-h几乎总是结伴出现。du -sh /home # 查看/home目录的总大小 du -sh * # 查看当前目录下所有文件和目录各自的大小-c(或--total): 在最后产生一个总计。当查看多个独立项目时特别有用。du -sch /var/log/* # 查看/var/log下每个子项的大小并显示总和--max-depthN:控制遍历深度的神器。网络热词中就有du max depth可见其重要性。它指定du统计到第几级子目录。du -h --max-depth1 /usr # 只显示/usr下一级子目录的大小--max-depth0的效果等同于-s只显示当前目录总计。这个参数能帮你快速定位大空间消耗发生在哪一层级是进行磁盘空间分析的第一步。3.3 进阶参数应对特殊场景-x(或--one-file-system): 这是一个极其重要但常被忽略的参数。它让du只统计当前文件系统上的文件忽略挂载点mount point。例如你想统计根目录/的大小但/home是一个独立分区并挂载在/home下。如果不加-xdu -sh /会尝试去遍历统计/home这个挂载点下的所有文件这可能是另一个巨大的磁盘导致统计时间漫长、结果错误。加上-x后遇到/home就会跳过。du -shx / # 正确统计根分区本身的大小--excludePATTERN: 排除匹配模式的文件或目录。支持通配符。在分析空间时你可能想排除某些已知的缓存目录如node_modules或.git。du -sh --exclude“*.iso” --exclude“./.cache” /data-a(或--all): 默认du只输出目录的大小。加上-a会同时列出所有文件的大小。输出会变得非常详细通常需要结合sort命令使用。--apparent-size: 显示文件的“逻辑大小”即ls -l看到的大小而非“物理大小”。这在评估网络传输数据量或文件内容大小时有用但对磁盘空间管理参考价值不大。-B(或--block-sizeSIZE): 强制使用指定的块大小单位如-BM表示以 MB 为单位输出-BG表示以 GB 为单位。比-h更统一适合脚本处理。3.4 参数组合与经典使用范例快速定位当前目录下哪个子目录最大du -sh --max-depth1 | sort -hr这里sort -hr是逆序排序-r人类可读的数字-h。这是空间清理前的标准侦察动作。找出指定目录下最大的10个文件结合findfind /var/log -type f -exec du -h {} | sort -rh | head -10这个命令组合威力强大find找出所有文件-exec du -h对它们执行du然后排序取前10。统计某类文件的总大小find . -name “*.log” -type f -exec du -ch {} | tail -1这能统计当前目录下所有.log文件的总大小。跨文件系统精确统计家目录大小du -shx ~因为/home通常是独立分区使用-x可以确保只统计用户家目录本身的内容不会误入其他挂载点。4. 生产环境实战du在磁盘空间排查中的高阶应用命令行参数是武器而排查思路是兵法。下面我们模拟几个真实的生产环境场景看如何运用du及其组合拳来解决问题。4.1 场景一根分区/空间告急快速定位罪魁祸首现象df -h显示/分区使用率超过 95%系统告警。排查步骤全局扫描确定方向cd / sudo du -sh --max-depth1 | sort -hr这条命令会列出根目录下所有一级子目录的大小排序。通常/var、/usr、/home是怀疑对象。假设发现/var异常巨大。逐层深入缩小范围cd /var sudo du -sh --max-depth1 | sort -hr继续在/var下执行可能发现/var/log或/var/lib很大。定位具体文件或日志# 如果是日志目录 cd /var/log sudo find . -type f -name “*.log” -exec du -h {} | sort -rh | head -20 # 或者使用更简单的命令查看大文件 sudo ls -lhS /var/log | head -20此时你很可能发现某个应用如 Nginx, Docker的日志文件如app.log已经增长到几十 GB。处理与确认对于日志文件可以使用truncate或echo “” file.log清空确保相关服务支持或者配置日志轮转logrotate。清理后再次运行du -sh /var/log和df -h确认空间是否释放。注意直接rm大日志文件后如果服务进程未重启空间可能不会立即释放即前述的“已删除未关闭文件”问题。此时需要重启相关服务或使用truncate命令。4.2 场景二du与df差异巨大寻找“幽灵空间”现象df显示磁盘快满了但用du逐级统计所有目录加起来的大小远小于df显示的已用空间。排查步骤检查已删除未关闭的文件sudo lsof L1 | grep deleted # 或者更精确地 sudo lsof | grep deleted这个命令会列出所有被进程打开但已被删除的文件状态为deleted并显示其大小和持有它的进程 PID。你会看到类似这样的输出java 12345 user 1w REG 8,1 1024000000 1234567 /path/to/file.log (deleted)这表示 PID 为 12345 的 Java 进程持有一个已删除的日志文件该文件仍占用约 1GB 空间。处理方案方案A推荐重启持有该文件的进程。重启后操作系统会回收该文件描述符空间立即释放。方案B如果无法重启可以找到该进程然后清空对应的文件描述符。首先找到文件描述符编号上面输出中的1w1就是 fd# 假设进程PID是12345文件描述符是1 ls -lh /proc/12345/fd/1 # 然后清空它危险确保你知道在做什么 : /proc/12345/fd/1注意方案B有风险可能中断进程的正常日志记录仅作为临时应急手段。检查文件系统预留空间sudo tune2fs -l /dev/sda1 | grep -i “block count” # 或者查看预留空间百分比 sudo tune2fs -l /dev/sda1 | grep -i “reserved”对于 xfs 文件系统使用xfs_info命令。如果预留空间比例过高比如根分区 5% 对于大硬盘来说可能很大可以考虑在磁盘空闲时适当调低tune2fs -m 1 /dev/sda1调整为 1%但这需要谨慎评估。4.3 场景三高效分析特定用户或目录的历史增长需求监控/data/uploads目录过去一周的空间增长情况找出增长最快的子目录。思路结合find按时间过滤和du统计。编写分析脚本#!/bin/bash TARGET_DIR“/data/uploads” # 找到7天前修改过的所有文件和目录统计大小 find “$TARGET_DIR” -type f -mtime -7 -exec du -ch {} | tail -1这个脚本能统计过去7天内被修改过的文件的总大小。要更精细可以每天运行一次du -sh $TARGET_DIR并将结果记录到日志中通过对比日志来观察增长趋势。使用ncdu工具进行交互式分析 虽然本文主角是du但必须提一下它的“增强版”——ncdu。它是一个基于 curses 库的交互式磁盘使用分析器可以看作du的图形化终端版本。# 安装 sudo apt install ncdu # Debian/Ubuntu sudo yum install ncdu # CentOS/RHEL # 使用 ncdu /data/uploads进入后可以用方向键浏览按d删除文件界面直观分析效率远超手动执行du命令组合。5. 性能、陷阱与替代方案关于du你必须知道的几件事du很强大但并非没有缺点。了解它的局限和替代方案能让你在合适的场景选择最合适的工具。5.1du的性能瓶颈与优化du需要遍历目录树并统计每个文件的磁盘块对于包含海量小文件如node_modules、邮件存储的目录du可能会运行得非常慢I/O 压力巨大。使用-x避免跨文件系统如前所述这能避免无意义的遍历。使用--max-depth限制深度如果你只关心顶层目录的大小就没必要遍历到底。在非业务高峰时段执行对于大型目录的分析最好在系统负载低的时候进行。考虑文件系统特性在ext4文件系统上du的元数据操作相对较重。而像btrfs或zfs这类支持快照和写时复制的文件系统du的行为会更复杂可能需要使用其自带的子命令如btrfs filesystem usage来获得更准确的空间信息。5.2 常见陷阱与误区权限问题普通用户运行du时对于没有读权限的目录或文件du会报错Permission denied并且不会统计其大小。这会导致统计结果偏小。因此统计系统目录时务必使用sudo。符号链接Soft Link默认情况下du会统计符号链接文件本身的大小很小而不会追踪到链接指向的目标。如果你希望du统计链接目标的大小需要使用-L或--dereference参数。注意这可能导致重复统计如果链接指向的是已统计过的目录内部或循环链接问题。稀疏文件Sparse File像虚拟机磁盘文件.qcow2,.vdi或数据库文件可能是稀疏文件。它们逻辑上很大但物理占用可能很小。du默认报告物理占用但du --apparent-size会报告逻辑大小两者差异可能极大。du统计的是磁盘占用不是文件内容总和这一点再怎么强调都不为过。一个 1KB 的文件占用 4KB 磁盘空间一个 1000 个硬链接的文件du会算 1000 次。这是理解du输出的一切基础。5.3 替代与互补工具df永远的搭档用于宏观把控文件系统容量和 inode 使用率df -i。ls对于快速查看单个文件或少量文件的逻辑大小ls -lh更直观。ncdu如前所述交互式分析的绝佳选择尤其适合探索性排查。btrfs/zfs专用命令如果你使用这些高级文件系统请忘记du和df的常规输出它们无法正确反映快照、克隆等特性下的空间使用。务必使用btrfs filesystem du、zfs list等原生命令。图形化工具如BaobabGNOME 的磁盘使用分析器、FilelightKDE等在桌面环境下可以提供更直观的可视化分析。du命令是 Linux 系统管理员的瑞士军刀之一其价值远不止于一个简单的“查看文件夹大小”的工具。从理解其与df的本质区别开始到熟练运用参数组合进行高效排查再到洞察其背后的文件系统原理和性能陷阱这是一个系统工程师成长的必经之路。下次再遇到磁盘空间告警时希望你能像一位经验丰富的侦探从容地拿起du这把放大镜结合lsof、find等工具迅速定位问题根源而不是盲目地删除文件。记住精准的洞察源于对基础工具的深刻理解。
返回列表