news 2026/10/2 21:50:01

Linux磁盘占用排查:du命令从基础到实战完全指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Linux磁盘占用排查:du命令从基础到实战完全指南

今天聊一下 Linux 下最常用的磁盘占用排查命令:du。不管你是在生产服务器上看到报警“磁盘空间不足”,还是本地开发环境莫名撑爆了根分区,总得先搞清楚哪个文件、哪个目录把空间给吃掉了。du 就是干这个的。

这个命令的核心能力是递归统计文件和目录的磁盘占用,配合排序和排除参数,可以快速锁定“到底是谁占了我的硬盘”。它和 df 这种查看分区整体使用率的工具完全不同,前者是“从下往上逐一把账目算清”,后者是“直接看总额还有多少余额”。这篇内容我会从最基础的用法开始,逐步深入到实战排查场景,顺带把我在运维过程中踩过的坑、试过的技巧都写出来,适合刚接触 Linux 的初学者,也适合已经会用但想系统梳理的运维同行。

我在实际使用中发现,du 这个命令看起来很“简单”,但它有一堆容易忽略的细节:为什么统计出来的空间大小和 df 对不上?为什么删除文件后磁盘空间没有释放?为什么小文件明明只有 100 字节却显示占用了 4K?这些问题不弄明白,排查磁盘问题时很容易走弯路。下面我从头到尾讲清楚。

1. 为什么需要 du 以及它和 df 的根本区别

很多人最开始分不清 du 和 df,以为两个都是看磁盘的命令,随便用哪个都行。实际上它们的统计口径完全不同,排查思路也因此不一样。

1.1 一句话理解 du

du 的全称是 disk usage,它的工作机制是进入你指定的目录,逐层递归地访问每一个子目录和文件,从文件系统读取每个对象的元数据里的块数信息,然后一层层累加汇总,最后输出该目录树的总占用。

你可以把它想象成:你想知道家里有多少存款,但银行给你的是总额,你反而要自己拿个小本子把每张银行卡、每笔理财、抽屉里的现金逐项记下来,最后加总。如果你只想知道某个目录装了多大,用du -sh /路径一条命令就搞定了。

1.2 du 和 df 的差异

df 的全称是 disk free,它查看的是整个文件系统、整个分区的使用情况,比如/dev/sda1挂载在/,总共 100G,已用 80G,剩余 20G。df 不关心具体是哪个目录用了这 80G,它只知道整个分区层面还剩多少。

du 则相反,它深入到目录内部,把每个文件占用的实际磁盘块数统计出来,最后汇总。所以排查“哪个目录把空间占满了”的正确答案一定是用 du,而不是 df。

我用一个直观的对比表来说明:

维度dfdu
统计对象文件系统/挂载点目录和文件
统计方式读取文件系统超级块信息递归遍历目录树
能否定位目录不能,只显示整体能,逐级列出
常用场景确认哪个分区满了确认哪个目录或文件占空间多
返回速度快,毫秒级慢,取决于目录大小

1.3 磁盘空间去哪儿了:先从系统层面排查

如果你接到了磁盘告警,我的建议是先用df -h看一遍所有挂载点,确认到底是哪个分区满了,同时也看一下当前工作目录所在文件系统是否是那个满的分区。这里有个经常出现的误区:你在/data下执行du -sh,结果发现占用很小,但df -h却显示/data所在磁盘已经 100% 满了,这种差异往往不是算错了,而是有隐藏的占用,后面我会专门讲这个问题。

2. 基础用法:从最简单的 du -sh 开始

我平时几乎天天用du -sh,因为它的输出最干净,只显示汇总大小,不打印一大串子目录路径。对于快速判断一个目录的整体体量,这是最顺手的方式。

2.1 查看当前目录总大小

直接在目录里执行:

du -sh .

输出结果可能是:

1.2G .

-s表示 summary,只输出总计;-h表示 human-readable,以 K、M、G 等单位显示。如果你不写-h,输出会是一堆以 KB 为单位的数字,比如 1258292,看起来非常吃力,所以我建议在任何地方都习惯性加上-h。

2.2 查看指定目录

查看特定路径时,直接跟上目录名即可:

du -sh /var/log du -sh /home/user du -sh /var/log /home/user /tmp

最后一条命令会一次性输出多个目录各自的占用,后面我会结合排序命令找出最大的那个。

2.3 单位选择:不要被默认的 4K 弄糊涂

-h是自动选择合适单位,但在脚本或者是需要统一口径时,可能需要固定单位:

  • -k:以 KB 为单位
  • -m:以 MB 为单位
  • -B 1:以字节为单位
  • --si:使用 1000 进制而不是 1024 进制,比如 1G 表示 1000M,而不是 1024M

很多人没注意到-h的“人类可读”并不是标准意义上的 1024 进制,GNU du 默认以 1024 为换算单位。如果某些软件或者云平台要求按 1000 进制计算,就用--si控制。

另外,细心的朋友可能会发现,一个只有 10 字节的小文件,du -h却显示 4.0K。这是因为磁盘按块分配空间,默认块大小是 4096 字节,一个文件至少要占一个块。所以 du 统计的是“实际占用的磁盘空间”,不是文件内容的“逻辑大小”。如果你要看书面的文件大小,用ls -l;如果要看占了多少磁盘块,用du。想单独看逻辑大小时可以加--apparent-size参数:

du -h --apparent-size somefile

这个参数在判断“一堆小文件实际占用”时很有用,因为稀疏文件、压缩文件、以及大量小文件场景下,逻辑大小和实际占用往往差异巨大。

2.4 隐藏文件与通配符细节

一个非常容易被忽略的坑是:du -sh *这个写法默认不会统计以点号开头的隐藏文件。如果你在某个目录下执行:

du -sh * | sort -h

发现所有输出加起来和du -sh .对不上,往往就是隐藏文件被漏掉了。比如用户的.cache、.local、.config这类目录,经常在不知不觉间积攒了十几个 G。

想包含隐藏文件,可以这么写:

du -sh .[!.]* * 2>/dev/null | sort -h

或者用更稳妥的方式:

du -sh ./* .[!.]* 2>/dev/null | sort -h

这里的.[!.]*会匹配.foo这种以点开头但第二字符不是点的项,2>/dev/null是为了过滤无权限访问时的错误信息。如果你不想要这种通配符的绕法,更推荐直接用下一节讲的--max-depth参数。

3. 进阶:统计子目录占用与排序

了解基础用法后,真正的高频场景是:一个大目录下有很多子目录,我要快速找出谁最大。这就需要控制 du 的递归深度,再把结果排序。

3.1 用 max-depth 控制层级

较新版本的 GNU du 支持--max-depth=N,只向下统计 N 层目录。我常用的写法是:

du -h --max-depth=1 /home

等价于:

du -h -d 1 /home

这条命令会列出 /home 下每一个直接子目录的大小,以及 /home 本身的总大小。--max-depth=1是最实用的参数,它避免了一屏刷不完的尴尬,同时又能把问题直接定位到一级目录。

如果想要看到两级:

du -h --max-depth=2 /home

还是那句建议:先用 depth 1,锁定嫌疑目录,再进入子目录继续 depth 1 排查,而不是一次性 depth 3 输出几百行。

3.2 对结果排序找出“大户”

光有数字还不够,得把最大的排在最前面。du 本身不带排序功能,我们需要把它和 sort 组合起来:

du -h --max-depth=1 /home | sort -h -r

这里关键点是sort -h,表示按照人类可读的数字大小排序,而不是按字典序。如果不加-h,你会看到9G排在100M前面,因为字母序里 “9” 大于 “1”。-r表示降序,最大的在最前。

更稳妥的写法是:

du -h --max-depth=1 /home 2>/dev/null | sort -h -r | head -20

只保留前 20 行,避免输出过多干扰判断。如果你所在环境是老版本 sort,不支持-h,也可以用:

du -k --max-depth=1 /home | sort -n -r | head -20

先统一以 KB 为单位排序,看够了再转成人类可读数字,不过系统里一般都会支持-h。

3.3 用 du 配合 find 处理特定文件

有时候你不需要统计整个目录树,只需要找出某些特定类型的大文件。比如查找当前目录下所有超过 100M 的日志文件:

find /var/log -type f -size +100M -exec du -h {} \;

这里的find负责筛选大文件,du -h再负责输出每个文件的实际磁盘占用。这种组合在排查“某个目录总大小正常,但某个单文件异常庞大”时非常有效。还可以配合xargs批量处理:

find /home -type f -size +500M -print0 | xargs -0 du -h | sort -rh

-print0和xargs -0的目的都是为了正确处理文件名里的空格和换行符,这是我踩过坑之后养成的习惯。如果文件名中有特殊字符,直接find ... | xargs du轻则统计错误,重则命令失败或误删文件。

3.4 排除日志或缓存目录

在实际服务器上,总有一些目录我们心里清楚它一定很大,暂时又不想看,比如/var/log下的历史日志,或者某个程序留下的缓存。为了避免它们干扰排查,可以用--exclude参数:

du -h --max-depth=1 --exclude=/var/log /var

或者用通配符排除所有.git目录:

du -h --max-depth=2 --exclude='*.git' /path/to/project

还有一个特别实用的场景:备份目录。很多项目在代码目录里有 node_modules、vendor、dist 等巨型目录,逐个统计时会刷满屏幕。这时候先排除掉它们,更快地看到真正需要手工分析的部分。等到定位完业务数据后,再单独去检查被排除的目录。

4. 实战场景:从“磁盘满”到“清理完成”的完整排查流程

讲了这么多参数,不如完整走一遍真实场景。假设我接到一个任务:某台服务器/分区 100%,网站开始报错,服务起不来。我需要快速找出是谁把磁盘占满了,并安全地做出处理。

4.1 场景初始化

先说明一下,我使用的系统是常见的 Linux 发行版,GNU 工具集。为了演练,我提前在一个测试目录里制造了“案发现场”:一个大日志目录、一个缓存目录、一些隐藏文件,还有一个被进程删除但仍然被占用的文件。

实际排查时第一步永远是:

df -h

输出大概长这样:

Filesystem Size Used Avail Use% Mounted on /dev/sda1 98G 98G 3.4M 100% / tmpfs 7.8G 0 7.8G 0% /dev/shm ...

确认根分区满了,下一步就该用 du 定位具体路径了。

4.2 第一轮:du 自上而下锁定目录

在根目录下执行:

du -h --max-depth=1 -x / 2>/dev/null | sort -h -r | head -10

注意我加了-x,这个参数的意思是统计时不要跨越文件系统边界。因为/proc、/sys、/dev等虚拟文件系统在 du 眼里如果递归下去又慢又没意义,还可能统计出和物理磁盘无关的数字。-x会让 du 只统计根文件系统上的目录。

输出可能是:

95G /opt 1.8G /var 12M /etc ...

一下子就锁定了/opt是最大的疑点。

4.3 第二轮:进入目标目录继续细分

紧接着:

du -h --max-depth=1 /opt 2>/dev/null | sort -h -r | head -20

输出:

92G /opt/application 2.1G /opt/backup 800M /opt/software ...

继续向/opt/application内部看:

du -h --max-depth=2 /opt/application 2>/dev/null | sort -h -r | head -20

最后定位到/opt/application/logs/下的access.log.20240101等历史日志文件,总大小 90G。这个逐层缩小的过程,就是标准的 du 排查法:从根开始,每次只往下看一层,永远把最大目录作为下一轮的入口。

4.4 第三轮:细看文件级占用

当目录下一层已经全是文件、没有子目录时,--max-depth就不好用了,可以用-a参数列出所有文件:

du -ah /opt/application/logs 2>/dev/null | sort -h -r | head -10

这里-a表示列出目录树中每个文件的占用,而不只是目录汇总。输出里单个文件的大小一目了然,直接就能判断哪个日志该归档,哪个缓存该清。

4.5 清理与验证

清理前强烈建议先和业务方确认哪些文件可以删除。如果只是一些滚动日志,常见的做法是压缩归档或者用truncate清空而不是直接rm。比如:

truncate -s 0 /opt/application/logs/access.log.20240101

清空文件之后,再执行:

df -h /

确认可用空间回升。如果还有报警,继续用 du 下一层找。

4.6 补充:被删除但未被释放的文件

这是排查磁盘空间时最反直觉的事:你用 du 统计某个目录,发现占用不大,但df -h还是满的。这时候十有八九是某个进程打开了文件,文件被rm删除,但进程还持有该文件描述符,所以文件的数据块并没有真正释放。

排查方法不是用 du,而是用 lsof:

lsof +L1

或者:

lsof / | grep deleted

这个命令能列出已经被删除、但仍然被进程打开的文件路径和 PID。看到结果后,和进程负责人确认是否可以重启该服务或重载配置。服务重启后,文件描述符释放,磁盘空间才会真正回来。很多新手在这个问题上卡上一整天,其实原因就这么简单。

5. 常见问题与避坑清单

把平时遇到的典型问题整理成一张速查表,方便翻阅:

现象可能原因解决方法
du -sh 和 df 对不上目录中统计时跳过了挂载点/虚拟文件系统,或有文件被删除但进程未释放加上-x,再用 lsof 排查L1
小文件显示 4K、8K磁盘块大小,文件至少要占一个块用--apparent-size查看逻辑大小
目录统计很慢子目录太多、文件太多,或跨越网络文件系统增加 exclude、限制深度、用-x
去掉 . 后总和小于总量隐藏文件被通配符漏掉了使用[-a]*或--max-depth
权限报错 Permission denied当前用户无权读取部分目录加 sudo,或用 2>/dev/null 忽略

5.1 为什么 du -sh 显示的比 df 用的空间小

这是出现频率最高的问题。核心原因是在同一个分区上,可能有文件系统预留空间、已删除但未释放的文件、以及 du 默认跳过挂载点。为了排查,我会习惯性地用du -x -sh /和df -h /对比。如果仍然差很多,重点看 lsof 的输出。我遇到过的最夸张的一次是,根分区显示满,但整个根目录 du 加起来只有 20G,最后发现是某个服务删除了两个 30G 的日志文件,进程一直没重启,空间一直没释放。

5.2 大目录统计耗时怎么办

统计几千个文件还好,遇到几百万个文件的目录时,du 可能要跑几分钟。这时候有几个技巧:一是使用ionice降低磁盘 IO 优先级,避免影响线上业务:

ionice -c 2 -n 7 du -sh /data

二是可以先把统计放到后台运行:

nohup du -h --max-depth=1 /data > du_result.txt 2>&1 &

等它跑完再看结果,期间不需要阻塞终端。三是如果只是日常监控,不要频繁对整个根目录跑深度统计,建议用定时任务把统计结果定期输出到文件,需要排查时直接翻记录。

5.3 权限不足的处理

普通用户执行 du 时经常看到:

du: cannot read directory '/root': Permission denied

这不会导致命令中断,只是跳过无权访问的目录,最终结果会比实际偏小。如果确实需要完整统计,就加 sudo 执行:

sudo du -sh /root

如果不想被错误信息刷屏,可以在命令后面加2>/dev/null。但在排查阶段我建议不要完全屏蔽 stderr,因为你可能需要分辨哪些目录是因为权限无法访问,以免漏掉真正的“大户”。

5.4 软链接和硬链接的计算差异

du 默认不会跟随符号链接展开统计,也就是说如果你在一个目录下建了软链接指向/opt,然后在当前目录执行du -sh,这个软链接本身只占一点点空间,不会去统计/opt的内容。这是合理的设计,否则一个软链接可能导致重复计算和遍历环。需要强制跟随的时候,用-L:

du -h -L /path/to/symlink

但生产环境里我基本不用-L,容易因循环链接导致结果重复或变慢。

硬链接则不同。多个硬链接指向同一个文件,磁盘空间只占一份。du 对硬链接的处理是,默认情况下同一个 inode 只统计一次,如果你用了-l参数才会把所有链接都分别计入。所以在普通场景下,du 是符合直觉的“实际磁盘占用”口径。

5.5 结果中的 . 表示什么

执行du -h --max-depth=1时,最后一行往往是一个点:

1.2G /home 12M /home/user 1.2G .

这个点在 du 输出里代表当前统计的根目录自身,也就是整个目录树的总大小。排序时如果不小心,可能把这一行混进子目录里。如果你只想看子目录,可以过滤掉它:

du -h --max-depth=1 /home 2>/dev/null | grep -v '/home$'

不过在实战中我通常保留这一行,因为直接就能看到总占用,方便和 df 做对比。

5.6 du 与 inode 耗尽的关系

最后补充一个很多人会混淆的知识点:磁盘空间满有两种情况,一种是容量满,另一种是 inode 满。du 只能看容量,看不出来 inode 是否耗尽。如果你的服务器明明df -h显示还有几十 G,但创建文件时却提示“No space left on device”,那很可能是 inode 不够了。

这时候应该用:

df -i /

查看 inode 使用率。如果 inode 使用率达到 100%,即使磁盘容量还有很多,也无法新建文件。对于大量小文件堆积的目录,尤其是缓存目录、消息队列积压目录,经常会出现这种问题。排查 inode 大户可以用:

find / -xdev -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -rn | head -20

这条命令会统计每个目录下文件数量最多的前 20 个位置。这里面的-xdev和 du 的-x一个思路,只检查当前分区,避免遍历挂载点。

我在实际工作中已经养成了一个习惯:每次清理磁盘前,一定先记录当前的 du 明细到临时文件,清理后再次对比,确认空间恢复到了预期。这样既方便事后审计,也能避免误删导致的服务异常。du 这个命令看似简单,但把它的参数吃透、把统计口径理解清楚,排查磁盘问题就能少走很多弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/2 21:49:50

SpringBoot+Vue在线教育系统源码:从环境搭建到二次开发全攻略

把这套项目真正跑起来之前,我先说一句大实话:网上号称"可直接运行"的源码很多,但绝大多数你都要花一晚上解决数据库版本、端口冲突、前端代理这三个问题。这套在线教育系统信息管理系统源码,SpringBoot 后端 Vue 前端 …

作者头像 李华
网站建设 2026/10/2 21:49:01

npm install 报错排查全指南:从原理到实战

开门见山说个很多人的困惑:一条npm install敲下去,运气好一杯水没喝完就装完了,运气差能卡在进度条上一个小时,弹出的报错还千奇百怪。更烦的是,同一个项目在别人电脑上一次过,到你手里就翻车。问题的根源在…

作者头像 李华
网站建设 2026/10/2 21:46:42

COLMAP点云可视化与6D位姿对齐:从二进制解析到Open3D/PCL实战

简介:这是一款面向三维重建与计算机视觉开发者的点云可视化工具,主要解决Colmap重建结果、pcd/ply点云以及6D位姿R|t难以直观查看的问题。工具支持加载Colmap输出的images、cameras、points3D、project四类文件,也兼容pcd、ply格式点云&#…

作者头像 李华
网站建设 2026/10/2 21:38:04

AutoGen多智能体协作框架实战:从核心概念到生产部署的避坑指南

1. AutoGen框架到底解决了什么问题第一次接触AutoGen是在一个多智能体协作的需求里,当时想让几个不同角色的模型互相配合完成一份行业调研报告,试过自己写调度逻辑,代码量直接爆炸,后来发现AutoGen这个框架,用下来确实…

作者头像 李华
网站建设 2026/10/2 21:37:20

AI漫剧工业化生产流水线:剧本生成到音画同步全链路实践

1. 这不是“AI剪辑课”,而是一套可落地的漫剧工业化生产流水线 你点开这个标题,第一反应可能是:“又一个教Stable Diffusion出图、用ElevenLabs配音、再塞进CapCut拉时间轴的三件套教程?”——我试过不下二十个类似标题的视频&…

作者头像 李华