尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Linux磁盘空间排查:du命令原理、实战技巧与df差异解析

Linux磁盘空间排查:du命令原理、实战技巧与df差异解析 1. 从一次磁盘告警说起为什么你需要掌握du命令那天下午我正在调试一个服务突然收到监控系统的告警邮件“服务器/data/logs目录磁盘使用率超过 90%”。这可不是小事日志爆满轻则导致服务无法写入新日志重则可能直接写满根分区让整个系统宕机。我立刻 SSH 连上去第一反应就是看看这个目录下到底是谁在“搞鬼”。是某个服务的日志文件失控滚动了还是临时文件没有及时清理如果只是简单地用ls -lh你只能看到当前目录下直接子文件的大小对于嵌套很深的目录结构这无异于盲人摸象。你需要一个能“透视”整个目录树并精准定位空间占用元凶的工具。在 Linux 的世界里这个工具就是duDisk Usage。对于任何一位 Linux 系统管理员、运维工程师甚至是后端开发者来说du命令都是工具箱里最基础也最不可或缺的一把瑞士军刀。它解决的问题非常直接快速、准确地评估文件和目录对磁盘空间的消耗情况。无论是日常的磁盘空间巡检、定位异常增长的文件还是清理工作前的“摸底调查”du都能提供关键数据。本文将带你深入du命令的方方面面不仅告诉你如何查看指定目录下各个文件大小及总体大小更会分享我在十多年运维生涯中积累的实战技巧和避坑指南让你下次面对磁盘空间告警时能从容应对一击即中。2.du命令核心解析参数、输出与工作原理在深入实战之前我们必须先理解du命令的基本语法和它到底在“算”什么。du命令的常规格式是du [选项] [文件或目录...]。如果不指定文件或目录它会默认分析当前目录。2.1 最常用的核心选项让我们先看几个你几乎每次都会用到的选项-h(human-readable)这是必选项。它会把以字节为单位的原始数字转换成人类易读的格式K、M、G、T。对比一下# 不使用 -h $ du /var/log 4 /var/log/private 8 /var/log/installer 205832 /var/log # 使用 -h $ du -h /var/log 4.0K /var/log/private 8.0K /var/log/installer 202M /var/log显然看到202M比看到205832要直观得多。这里的M代表 Mebibyte (MiB)在二进制体系中1 MiB 1024 KiB1 KiB 1024 Bytes。这是 Linux 工具的标准做法。-s(summarize)只显示指定目录的总大小而不列出其内部每一个子项。当你只关心一个目录整体占用了多少空间时这个选项非常高效。$ du -sh /home 47G /home一行输出干净利落地告诉你/home目录总共用了 47G。-c(total)在最后一行产生一个总计。当同时查看多个目录时这个总计很有用。它常与-s联用。$ du -sch /var/log /var/cache 202M /var/log 154M /var/cache 356M total--max-depthN控制命令遍历目录的深度。这是定位问题的关键参数。--max-depth0等同于-s只显示目标目录本身的总大小。--max-depth1显示目标目录及其直接子目录或文件的大小。这是最常用的深度可以快速看到一级子项的空间分布。$ du -h --max-depth1 /var 154M /var/cache 0 /var/lock 0 /var/mail 202M /var/log ... (其他目录) 1.2G /var2.2du与df的差异一个经典的“空间去哪了”之谜在相关热词里我看到了centos du df 磁盘空间差太多。这确实是一个高频困惑点。du(Disk Usage) 和df(Disk Free) 统计的是不同的东西。df报告文件系统的磁盘空间使用情况。它读取的是文件系统超级块superblock中的元数据统计的是已被分配used和未被分配free的数据块。这些数据块可能正在被文件使用也可能被已删除但仍被进程占用的文件占用或者干脆就是文件系统的预留空间、元数据区。du通过遍历目录树累加每个文件所占用的数据块数量然后乘以块大小通常是 4KiB来计算空间。为什么会出现差异已删除但未释放的文件如果一个文件被删除rm但仍有进程正在打开它例如一个日志文件被服务进程写入后又被误删df会显示空间仍被占用因为数据块尚未释放但du遍历不到这个已删除的文件名所以不会计入。这是最常见的原因。可以用lsof | grep deleted命令查找这类文件。文件系统预留空间Ext3/Ext4 等文件系统默认会预留 5% 的空间给 root 用户以防普通用户写满磁盘导致系统无法运行。这部分空间df会算在Used里但du不会统计。稀疏文件 (Sparse Files)像虚拟机磁盘镜像.qcow2,.vmdk或数据库文件可能声明了一个很大的逻辑大小但实际只占用少量物理块。du默认报告物理占用-b或--apparent-size可以看逻辑大小而ls -l看到的是逻辑大小这也会造成认知差异。文件系统元数据如 Journal日志文件系统如 Ext4的日志区占用空间df会计入du不计。所以当du和df结果对不上时不要慌张这通常是正常的。你需要结合lsof和df -i查看 inode 使用情况等命令进行综合判断。3. 实战定位目录空间占用与排序分析现在我们回到开头的那个告警场景/data/logs目录快满了。我们该如何一步步定位问题3.1 第一步查看目录总体大小与一级子项分布首先我们得知道总共有多少“存货”以及大致是哪些“品类”占了大头。$ du -sh /data/logs 89G /data/logs $ du -h --max-depth1 /data/logs 12K /data/logs/nginx 4.0G /data/logs/app_a 82G /data/logs/app_b 1.2G /data/logs/app_c 89G /data/logs一目了然app_b这个服务的日志目录是绝对的“空间杀手”占了 82G。问题范围立刻从 89G 缩小到了 82G。3.2 第二步深入“问题目录”按大小排序接下来我们进入app_b目录并希望看到里面最大的文件或子目录。这里就需要结合sort命令了。du本身不排序默认输出顺序依赖于文件系统的读取顺序通常按 inode 编号或文件名。# 进入目录查看所有文件和子目录的大小深度为1并按人类可读的数字逆序排序 $ cd /data/logs/app_b $ du -h --max-depth1 | sort -hr 82G . 76G ./application.log.20231015 4.1G ./application.log 987M ./debug.log.20231014 ... (其他较小文件)sort -hr是关键-h让sort能正确理解人类可读的数值如 82G, 4.1G而不是进行字符串排序。-r逆序最大的排在最前面。踩坑提示如果你在 MacOS 的终端里操作BSD 版本的sort可能不支持-h参数。一个替代方案是使用-n数字排序但前提是du不能使用-h输出。你可以这样做du -k --max-depth1 | sort -nr。-k选项让du以 KiB 为单位输出这样就是纯数字可以用-n排序。不过这样可读性会差一些。3.3 第三步处理已滚动的历史日志文件从排序结果看一个名为application.log.20231015的历史日志文件独占 76G。这很可能是因为日志切割工具如logrotate配置了按日期切割但忘记配置或错误配置了删除旧日志的策略maxage,maxsize。此时你需要检查logrotate的配置文件通常在/etc/logrotate.d/下确认对于app_b的日志是否有类似maxsize 100M,daily,rotate 7保留最近7天这样的配置。如果没有就需要添加并手动触发一次logrotate或者直接安全地删除这些过期文件。安全删除建议对于确定要删除的大文件不要直接用rm尤其是当磁盘空间非常紧张时。因为rm只是删除文件名链接如果文件正被进程打开空间并不会立即释放。更好的做法是使用truncate或:命令清空文件内容或者用echo filename这样能立即释放磁盘空间。确认服务不受影响后再安排重启相关服务以彻底删除文件句柄或者直接rm。# 清空文件内容文件大小变为0空间立即释放 $ truncate -s 0 /data/logs/app_b/application.log.20231015 # 或者 $ : /data/logs/app_b/application.log.202310154. 高级技巧与场景化应用掌握了基础操作我们来看看一些更高效、更贴合复杂场景的用法。4.1 排除特定文件或目录有时目录里包含一些你明知很大但又不想在统计中看到的文件比如虚拟机镜像、Docker 容器数据卷或者特定的缓存目录。du本身没有内置的排除模式但我们可以结合find命令来实现。例如我想统计/home目录大小但排除所有.cache目录和.iso文件$ find /home -type f ! -name *.iso ! -path */.cache/* -exec du -ch {} | tail -1这个命令有点复杂它先用find找到所有非.iso文件且路径中不包含/.cache/的文件然后交给du -c计算最后用tail -1取总计行。但注意这种方法对于排除目录并不完美因为find仍然会进入.cache目录去匹配文件可能会影响性能。一个更直观的方法是使用--exclude参数注意这是 GNUdu的扩展并非所有系统都支持但在大多数 Linux 发行版上可用$ du -sh --exclude.cache --exclude*.iso /home这个命令就清晰多了它会忽略所有名为.cache的目录和所有以.iso结尾的文件。4.2 统计特定类型文件的总大小开发中常需要知道某个项目里所有图片、日志或者编译产出如.o,.class占了多少空间。# 统计当前目录及子目录下所有 .log 文件的总大小 $ find . -name *.log -type f -exec du -ch {} | tail -1 # 统计所有 .jpg 和 .png 图片的总大小 $ find . \( -name *.jpg -o -name *.png \) -type f -exec du -ch {} | tail -14.3 与awk结合进行自动化分析与告警在脚本中我们可能需要设定阈值进行自动化检查。awk是处理du文本输出的利器。#!/bin/bash TARGET_DIR/data/logs THRESHOLD_GB50 # 获取目录大小以字节为单位并转换为GB size_gb$(du -sb $TARGET_DIR | awk {print $1/1024/1024/1024}) # 使用bc进行浮点数比较 if (( $(echo $size_gb $THRESHOLD_GB | bc -l) )); then echo 警告目录 $TARGET_DIR 大小为 ${size_gb}GB已超过阈值 ${THRESHOLD_GB}GB。 # 可以在这里添加发送邮件、钉钉消息等告警逻辑 # 同时可以自动运行分析命令将最大的10个文件列出来附在告警信息里 echo 空间占用最大的10个文件/目录 du -ah $TARGET_DIR | sort -rh | head -11 # head -11 因为第一行是总计 fi这个脚本定期运行比如放入 crontab就能实现磁盘空间的主动监控。4.4 处理包含大量文件的目录如果你对一个包含数十万甚至上百万文件的目录比如邮件队列、图片存储目录直接运行du它可能会运行非常久因为需要为每个文件执行stat系统调用。一个优化技巧是使用du的--files0-from参数如果支持或者利用find的-print0和xargs -0来更高效地处理。另外对于海量小文件文件系统本身的元数据inode也可能被耗尽此时df -i会显示 inode 使用率 100%即使df -h显示还有空间。这也是du和df差异的一个潜在原因。5. 图形化替代方案与可视化工具虽然命令行高效但在向非技术同事汇报或者需要更直观展示时图形化工具很有帮助。ncdu(NCurses Disk Usage)这是一个基于文本界面的交互式du工具。它会在终端里绘制一个可导航的界面让你用键盘方向键浏览目录树按大小排序甚至可以直接删除文件。安装简单apt install ncdu或yum install ncdu是命令行爱好者的首选可视化工具。$ ncdu /data/logs运行后你会看到一个清晰的层级结构按大小降序排列交互体验极佳。baobab(Disk Usage Analyzer)如果你在使用 GNOME 桌面环境baobab提供了一个完整的图形化界面用树状图和旭日图sunburst直观地展示磁盘使用情况。它同样支持扫描远程目录通过 GVfs功能强大。gdmap另一个图形化工具使用树状图展示视觉效果不错。对于日常的快速分析和问题定位我个人的习惯是首选ncdu。它既保留了命令行的效率又提供了图形化的直观无需离开终端在远程服务器上也能完美工作。
返回列表