Linux服务器磁盘满排查实战:df定位、du下钻与空间释放
看到“Linux服务器磁盘满了”这类告警我估计不少朋友都经历过那种手忙脚乱的感觉。登录服务器第一件事就是想弄清楚到底哪个文件夹把空间吃掉了。这个需求听起来太简单了不就是 du 一下目录大小么可真到排查的时候你会发现 df 和 du 数字对不上、几百万文件的大目录统计到怀疑人生、删了文件空间却不释放这些问题单独拎出来都能耽误半天。这篇文章就把我在生产服务器上排查磁盘占用的一套完整思路写下来从 df 分区定位、du 目录下钻到最后的自动化监控希望能给遇到同样问题的读者一些参考。1. 分区告警之后先看“满”的到底是哪块地盘1.1 df -h 输出读法每列都代表什么很多新手一上来就执行du -sh /*把整个根目录从头扫到尾。这个方法不能说错但效率通常非常低。实际服务器往往挂载了多块磁盘根分区、/data、/var/log 可能各自独立你对着根目录一通扫描看到的可能是好几块盘的叠加结果既慢又没有重点。正确顺序是先跑一句df -h输出大概是这个样子的Filesystem Size Used Avail Use% Mounted on /dev/vda1 20G 18G 1.6G 93% / /dev/vdb1 200G 150G 50G 76% /data tmpfs 3.9G 0 3.9G 0% /dev/shm各列的意思大家多少都知道一点我重点说几个容易忽略的细节Filesystem底层设备或伪文件系统。看到/dev/vdb1就知道这是块独立的磁盘分区后面排查范围可以缩小。Size / Used / Avail这三列的单位是 G是分区维度的总量不是目录维度的占用。Use%使用率。这个数字过高就要警惕但也要注意ext4/xfs 默认会给 root 保留约 5% 的空间所以看到 93% 其实已经非常危险了普通用户实际能用的空间可能比 Avail 显示的数字还要少。Mounted on挂载点。它决定了你后续du要从哪个入口去追。只要看到告警说“某目录所在分区使用率超过90%”第一件事一定是df -h确认是哪块盘满了而不是直接扫目录。分区都没确定扫目录等于大海捞针。1.2 df 和 du 数字对不上八成是这三个原因定位到具体分区后接下来的操作通常是du -sh /data看目录总大小。但这里会出现一个让很多人困惑的现象df 显示 /data 分区用了 150Gdu -sh /data统计出来的结果却只有 120G差的 30G 去哪了我见过太多人被这个问题卡住其实原因基本集中在以下三类**第一类已删除但仍有进程占用的文件。**这是最常见也最隐蔽的一种。某个进程打开了一个日志文件后来运维把它 rm 掉了但进程还持有这个文件的文件描述符。此时这个文件的目录项已经消失du从目录树往下数不会统计到它但它占用的磁盘块并没有释放df仍然把它算进 Used。解决办法是用lsof L1 | grep deleted找到这些“死文件”然后重启对应的进程空间才会真正释放。**第二类子目录里挂着独立文件系统。**比如 /data 下面还单独挂载了 /data/mysql 这块盘。df -h会分别显示两块盘的使用率而du -sh /data默认会顺着目录结构往下钻把 /data/mysql 里的内容也统计进去。这不是错但会干扰你判断“到底哪一层目录占用最大”。排查时最好先df -hT或mount看一眼子挂载点再决定du的扫描范围必要时加-x参数跨越或不跨越文件系统边界。**第三类稀疏文件与块对齐误差。**稀疏文件在逻辑上很大比如一个虚拟磁盘镜像ls -l 看是 100G但实际占用可能只有 2G。du默认统计的是实际占用的块大小所以它和文件的显示大小不一致是正常的。另外文件系统按块分配空间一个 1KB 的文件也占用一个 4KB 块日积月累这部分误差也不小但通常不至于到 GB 级别。搞清楚了 df 和 du 的视角差异后面用 du 做目录下钻才有意义。df 是“分区视角”du 是“目录树视角”两者的差别就是上面这些玄机所在。2. du 参数的实战拆解几种高频组合与背后的逻辑2.1 最常用的一组命令一层目录加排序du如果不带参数直接跑会把目录树下所有文件全部递归列出来那个输出长度足够刷几十屏。实际排查中我反复用的其实就那么几个组合。第一步统计指定分区下所有一级目录的大小并按大小排序。du -h --max-depth1 /data | sort -rh这条命令算是我日常使用频率最高的一条。-h表示人类可读输出 K/M/G 这样的单位--max-depth1限制递归深度只统计一层子目录sort -rh则是按可读数字的大小倒序排列让最大的目录排在前面。输出示例80G /data/mysql 30G /data/logs 25G /data/backup 8G /data/app 2G /data/tmp一眼望去针对 /data 分区的空间分布就清晰了大概率问题出在 mysql 和 logs 里。第二步只统计单个目录不列子项。du -sh /data/mysql-s是汇总把整个目录的大小合并成一行输出。这个参数在脚本里尤其好用因为输出干净、好解析。第三步想把文件也一起排进来--max-depth1会同时统计该目录下的普通文件有些时候大文件不在子目录里而在目录根部躺着这时候这个深度设置正好把文件和子目录一起看到了。2.2 参数设计逻辑与两种视角这几个参数背后其实反映了 du 的两种核心视角汇总视角-s就是把你关心的一整棵树压缩成一个数字适合判断“这个目录总共有多大”。下钻视角--max-depthN控制在第几层停止适合逐层定位从分区看到一级目录再从一级目录看到二级目录像剥洋葱一样一层层进去。理解了这个逻辑遇到特殊需求时你就能自己组合参数而不是死记命令。比如想看两层深度就写--max-depth2想排除某个缓存目录就加上--exclude*/cache想只看大于 1G 的目录就加-t 1G。一个个试总能得到想要的结果。有人可能会问为什么不直接用ls看目录大小因为ls -l显示的目录大小只是目录本身元数据块的大小通常在 4KB 到几十 KB 之间跟目录里装了多少文件完全没有关系。只有du会递归统计目录下所有内容才是真正的体积。2.3 容易被忽略的几个可选参数除了上面这些还有几个参数在特定场景下很实用参数作用典型场景-x/--one-file-system不跨越文件系统边界只想统计本分区的目录占用--excludepattern排除匹配路径跳过缓存、日志等无关目录-t/--threshold只显示大于指定大小的条目过滤小目录聚焦大头-m/-k强制以 MB / KB 输出脚本解析比-h更稳定--apparent-size显示逻辑大小而非物理块占用排查稀疏文件--time显示目录最后修改时间判断临时目录是否长期不清理尤其要注意-h和脚本的关系人类可读的输出很好看但如果想在脚本里做数值比较最好用-m固定单位否则 2G 和 200M 混在一起解析会非常痛苦。我早期写过不少统计脚本就是被这种单位混杂问题坑过。3. 一次完整排查实录从 95% 告警到定位真正的大文件3.1 第一层扫描给 /data 做个体检理论说多了还是用一次实际排查过程来串一遍。假设某天收到监控告警/data 分区使用率达到 95%。登录服务器后我按刚才的顺序来一遍。先看分区现状df -h /dataFilesystem Size Used Avail Use% Mounted on /dev/vdb1 200G 190G 10G 95% /data确认就是这块盘的问题。然后执行第一层扫描du -h --max-depth1 /data | sort -rh结果发现120G /data/mysql 45G /data/logs 18G /data/backup 5G /data/app 2G /data/tmp大头很明显mysql 占了 120Glogs 占了 45G。接下来就进入下钻环节。3.2 逐层下钻找到 binlog 目录并确认文件先看 mysql 目录里是谁在“吃”空间du -h --max-depth1 /data/mysql | sort -rh输出可能如下60G /data/mysql/data 45G /data/mysql/binlog 12G /data/mysql/tmp 3G /data/mysql/undobinlog 目录 45G这是二进制日志通常是数据库主从同步和恢复用的长时间不清理会非常膨胀。再往下钻一层直接定位到具体的 binlog 文件du -h --max-depth1 /data/mysql/binlog | sort -rh | head -20这时候看到的是一串带时间戳的文件比如mysql-bin.000123这类。结合文件的最后修改时间可以快速判断哪些是几天甚至几周前的旧文件确认不再被主从复制的MASTER_LOG_FILE指向之后才执行清理。直接删 binlog 而不考虑主从同步需求是会出大事故的这一点必须确认清楚再动手。3.3 删完文件空间没变用 lsof 找“隐形死文件”清理完 binlog 后我习惯性地再执行一次df -h /data结果发现使用率几乎没变。如果你也遇到这种情况不要怀疑自己删错文件大概率是文件被进程占用了。这时候用lsof L1 | grep deleted输出里能看到类似这样的行mysqld 12345 user 21w REG 253,1 4294967296 1048577 /data/mysql/binlog/mysql-bin.000120 (deleted)说明这个 binlog 文件虽然被删了但 mysqld 进程还开着它的文件描述符空间一直占着。解决办法只能是对相关服务进行优雅重启或者让进程重新打开日志文件比如执行FLUSH LOGS之后确认旧文件句柄释放。重启之前要和业务侧确认好在低峰期操作避免影响线上服务。这一趟下来120G 的 mysql 大头被拆解成 binlog、data、tmp 几个子项真正的问题也就浮出水面了。整个排查链路总结起来就是df 确认分区 → du 一层层下钻 → 定位大目录/大文件 → 处理特殊占用情况每一步都有明确的动作。4. 统计慢到怀疑人生大目录扫描的性能优化4.1 慢的根源不在命令在 IO 和文件数量有些目录尤其像应用日志、数据库数据文件目录动不动就是几百万个文件。这时候你再跑du -sh /data可能等上十几分钟甚至几十分钟都没有输出。很多人以为是 du 这个命令效率低其实不然。du 的统计逻辑是遍历目录下的每一个 inode对每个文件执行一次 stat 系统调用读取它占用的块数。文件数量越多、目录层级越深、磁盘 IO 越忙耗时就越长。如果遇到 NFS 或其他网络文件系统每次 stat 都有网络往返那速度更是慢到让人崩溃。了解这个原理后优化思路就清晰了不是换命令而是减少 du 的工作量。4.2 让扫描“低调”一点ionice、nice 与 nohup排查动作本身不能成为新的故障源这是运维里很重要的一条原则。一个全盘 du 扫描如果直接跑到生产环境的主磁盘上会跟业务抢 IO磁盘响应时间飙升可能比原来的磁盘满还要麻烦。有几个基本操作可以降低扫描对系统的影响ionice -c3 nice -n 19 du -h --max-depth1 /data | sort -rh /tmp/disk_report.txtionice -c3把 IO 调度等级设为 idle只有磁盘空闲时才让扫描跑业务 IO 永远是优先的。nice -n 19降低 CPU 优先级防止统计进程抢 CPU。输出重定向到文件避免终端会话断开导致任务中断。如果目录实在太大还可以放到后台跑nohup du -h --max-depth2 /data | sort -rh /tmp/disk_report.txt 21 然后继续做别的事过一会儿再看结果。这样既不阻塞排查流程也不会误伤线上服务。另外统计分析时完全可以先用--max-depth1做粗粒度扫描定位到具体一级目录后再单独对那一两个大目录做更深的统计而不是一次性全盘--max-depth3。分级下钻既能快速找到目标又避免了无谓的全量扫描这个思路比任何参数优化都更关键。4.3 inode 维度分区可能没满但文件数爆了排查磁盘占用时还有一个经常被忽略的维度inode。有些场景下 df 显示 Available 还有很多但系统却报错“No space left on device”这通常是 inode 耗尽了。使用命令df -i查看 inode 使用率。如果某个分区的 IUse% 接近 100%说明文件数量太多即使单个文件都很小也已经把分区撑爆了。这种情况多发生在消息队列的临时文件目录、小文件缓存目录、或各种程序疯狂写日志的目录里。定位文件数量最多的目录可以用find /data -xdev -type f | awk -F/ {print $2/$3} | sort | uniq -c | sort -rn | head这条命令统计各二级目录下的文件数量帮你在 inode 维度快速找到“文件海洋”。特别适合那种空间看似够用、但目录条目爆炸的场景。5. 把偶发排查变成定期动作目录空间快照与趋势观察5.1 一条 crontab 加一个脚本留下历史快照磁盘空间不是一天涨起来的。与其每次等到告警再紧急排查不如让统计动作定时自动跑留下历史快照。这样既能在告警到来时快速对比“上次什么样这次什么样”也能提前发现哪些目录在持续增长。一个很轻量的做法是写一个统计脚本定时执行并把结果写到带日期后缀的文件里#!/bin/bash SNAPSHOT_DIR/var/log/disk_snapshots mkdir -p $SNAPSHOT_DIR du -h --max-depth2 /data | sort -rh $SNAPSHOT_DIR/disk_$(date %Y%m%d).txt然后加入 crontab0 2 * * 0 /usr/local/bin/disk_snapshot.sh每周日凌晨两点跑一次对业务影响最小。时间一长目录里就积累了一批历史快照文件。5.2 快照对比找到持续“变胖”的目录有了快照对比就很简单。想快速看最近一周哪些目录变大可以用paste (sort /var/log/disk_snapshots/disk_$(date -d last week %Y%m%d).txt) \ (sort /var/log/disk_snapshots/disk_$(date %Y%m%d).txt) | \ awk {split($1,a,); print $1, $4}不过这个写法在生产环境里不一定顺手我更喜欢直接看两个文件里 top 20 目录的差异或者用一个简单循环把每个目录的历史大小拼成表。比如先awk {print $2, $1}把目录名放第一列再用join按目录名关联两个快照最后计算差值join -j 1 (awk {print $2, $1} 快照A) (awk {print $2, $1} 快照B) | awk {print $3-$2, $1} | sort -rn | head -20这里的关键在于快照格式要统一所以我脚本里用-h虽然看起来直观但在做数值对比时其实不方便更推荐用du -m以 MB 为单位输出保证脚本可解析。5.3 交互式工具与脚本化建议如果想在命令行里更直观地浏览目录大小分布我非常推荐试试ncdu。它是一款交互式磁盘使用分析工具安装后一条命令即可进入 TUI 界面支持方向键移动、回车进入子目录、d 删除条目视觉上比一屏一屏的命令输出舒服不少。ncdu /data第一次运行会花一些时间遍历目录之后就可以像逛文件管理器一样快速查看所有子目录占比。它本质上还是基于 du 的统计逻辑但交互体验好很多。服务器上没有图形界面时这个工具几乎是首选。如果你的服务器不方便安装额外工具那就坚持用好 du sort find 这套组合拳。还需要注意一点不要在生产环境的高峰期频繁跑全盘 du即使加了 ionice 也可能有影响尽量安排在业务低峰期。把这种统计做成每周的例行任务很多问题会在真正变成故障之前就被你发现。说到底磁盘空间排查这件事核心不是背会多少条命令而是形成一套“分区定位 → 目录下钻 → 特殊占用处理 → 长期监控”的闭环思路。我个人的习惯是每次紧急排查之后都会顺手把这个目录的月度增长趋势记录下来几次之后基本就能说出哪个目录是稳定增长、哪个目录属于瞬时波动。提前发现异常永远比事后救火值得投入。

相关新闻

隐马尔可夫模型在孤立字语音识别中的原理与MATLAB实现

隐马尔可夫模型在孤立字语音识别中的原理与MATLAB实现

简介:本资源是一套基于隐马尔可夫模型(HMM)实现孤立字语音识别的完整MATLAB工程代码,面向语音信号处理初学者、模式识别课程学习者及低起点科研实践者,解决从语音特征提取、HMM建模训练到识别解码的全流程技术落地问题…

2026/10/19 2:51:53 阅读更多 →
Django Admin二次开发:全方位获取当前登录用户实战指南

Django Admin二次开发:全方位获取当前登录用户实战指南

在给某个内部管理系统做Django Admin二次开发的时候,我遇到的第一道坎就是怎么拿到当前登录用户。听起来很简单,不就是request.user吗?但实际上Django Admin里涉及“当前用户”的场景远比想象中复杂:列表页要做数据权限过滤、保存…

2026/10/19 2:51:53 阅读更多 →
HMM语音识别原理:从MFCC到Viterbi的完整MATLAB实现

HMM语音识别原理:从MFCC到Viterbi的完整MATLAB实现

简介:本资源是一套基于隐马尔可夫模型(HMM)实现孤立字语音识别的完整MATLAB工程代码,面向语音信号处理初学者、模式识别课程学习者及低起点科研实践者,解决从语音特征提取、HMM建模训练到识别解码的全流程技术落地问题…

2026/10/19 2:51:53 阅读更多 →

最新新闻

Keras实现DCGAN:从零搭建稳定图像生成模型

Keras实现DCGAN:从零搭建稳定图像生成模型

1. 从零理解 DCGAN:为什么它比普通 GAN 更值得上手搞深度学习的人多少都碰过 GAN,但真正自己动手从零搭一个能跑出结果的,比例其实不高。原因也简单——GAN 的训练出了名的难伺候,判别器和生成器稍微不平衡就崩,要么生…

2026/10/19 4:28:45 阅读更多 →
从零实现DCGAN:Keras生成对抗网络实战与调参避坑指南

从零实现DCGAN:Keras生成对抗网络实战与调参避坑指南

1. 从零理解DCGAN:为什么它值得你花时间动手搭一遍如果你刚接触生成模型,大概率第一个听到的名词就是GAN。而DCGAN,全称Deep Convolutional Generative Adversarial Networks,是把卷积神经网络真正跑通、跑稳的那套方案。我最早接…

2026/10/19 4:28:45 阅读更多 →
AI Agent从零搭建指南:模型、记忆、工具与规划全解析

AI Agent从零搭建指南:模型、记忆、工具与规划全解析

先泼一盆冷水:如果你以为AI Agent是装个框架、填个API Key、写几句Prompt就能跑起来的玩意儿,那这篇文章可能不太适合你。如果你想知道为什么同样用大模型,别人能做出自动整理周报、主动查数据、自己决策调度的Agent,而你的项目却…

2026/10/19 4:28:45 阅读更多 →
Flutter布局基石:Row、Column、Container从入门到实战

Flutter布局基石:Row、Column、Container从入门到实战

1. 内容整体设计与思路拆解1.1 为什么布局基础要从这三个组件开始入行Flutter的人,第一个绕不开的坎就是布局。官方文档里布局相关的组件有几十个,Stack、Flex、Wrap、Flow、CustomMultiChildLayout……名字都能念,真到写界面的时候&#xff…

2026/10/19 4:28:45 阅读更多 →
Java常量与数据类型全解析

Java常量与数据类型全解析

1.对于字面常量, 咱们得弄明白这是个啥回事儿, 这里面分好了几种类型, 第一类叫做字符串常量, 第二类叫做整形常量,第三类叫做浮点型常量, 第四类叫做字符常量, 第五类叫做布尔常量, 还有一类叫做空常量。被final修饰之后, size变量就变成字面常量了, 它是不可以再进行修改的。…

2026/10/19 4:28:45 阅读更多 →
OpenCode终端AI编程助手:从安装到Agent模式实战全指南

OpenCode终端AI编程助手:从安装到Agent模式实战全指南

最近大半年,我几乎把一半的编码时间都交给了终端里的 AI 助手。OpenCode 算是我试过的工具里,最接近“直接在项目里部署一个能帮你写代码的同事”的那一个。它本质是一个运行在终端里的开源 AI 编程助手,不走网页、不靠 IDE 插件,…

2026/10/19 4:27:44 阅读更多 →

日新闻

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

频率跟踪型PWM电源设计:臭氧发生器谐振点漂移与软开关实现

简介:本资源为电源技术方向的学术研究文档,聚焦介质阻挡放电型臭氧发生器电源的频率跟踪型PWM控制策略,面向电力电子、高压电源及臭氧应用领域的科研人员与工程技术人员。针对负载呈容性、等效电容随外加电压升高而增大、谐振频率随之漂移的难…

2026/10/19 0:00:47 阅读更多 →
Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

Vibe Coding 遇上 TaoToken:把开发者思维圣殿的灵感流接入统一 Key 通道

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 0:00:47 阅读更多 →
HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

HundredCV-Chat话题建模实战教程:利用4,871个内置话题标签构建主题分析系统

【免费下载链接】HundredCV-Chat 项目地址: https://ai.gitcode.com/hf_mirrors/Jax-dan/HundredCV-Chat 点击查看 免费下载 HundredCV-Chat 是一个由 100 位青年简历数据开发而来的中文多轮对话数据集,共包含 24,750 组日常闲聊对话和 4,871 个话题标签…

2026/10/19 0:00:47 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/19 1:30:52 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/19 2:54:50 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →