尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

Linux服务器磁盘爆满排查与清理:从df -h到inode耗尽

发布时间:2026/9/29 15:44:57

资讯中心
01
ARTICLE

Linux服务器磁盘爆满排查与清理:从df -h到inode耗尽

Linux服务器磁盘爆满排查与清理:从df -h到inode耗尽
半夜两点手机警报响了。打开短信一看服务器磁盘使用率超过95%已触发告警阈值。这应该是每个运维人都经历过的场景也是运维群和救火现场出镜率最高的故障类型之一——Linux服务器磁盘爆满。这篇文章不打算给你灌概念直接讲排查思路和操作。目标读者有三类人刚接手服务器的新运维被同事拉去救火的后端开发以及自己租了Linux云主机跑服务、跑了半年突然发现磁盘100%的独立站长。看不懂底层原理没关系按命令照做基本能在一个小时内把问题揪出来处理掉。先给结论磁盘爆满这件事我实际处理过的案子里大概80%都出在日志文件、容器日志和包管理器缓存上真正被业务数据写满的反而没那么多。但最坑人的不是满而是df看着没满服务却死活写不进文件的隐蔽场景这种通常和inode耗尽有关。往下看你就知道我说的是什么。1. 第一步先判断是真满了还是假满了1.1 看容量别只盯着百分比先跑这两条命令排查磁盘爆满的第一个动作很多人上来就跑df -h看到Use% 99%就慌神马上开始找文件删。这个方向对了一半但有个隐患你把大文件删干净了磁盘还是满的这时候你才发现真正的问题不在容量而在节点数。我的习惯是同时跑两条命令df -h df -i前者看文件系统容量后者看inode使用率。df -h的输出大家都很熟悉就是每个挂载点用了多少、还剩多少。但df -i很多人平时根本不看输出的是inode总数、已用、剩余和百分比。为什么要看inode我用个不严谨但容易理解的类比硬盘容量相当于仓库的容积inode相当于仓库里货架的编号。仓库再空如果货架编号全被占了你就没法往货架上放新货。所以当inode用满文件系统已经无法创建任何新文件而磁盘空间还有富余——这是环境最恶劣的假满。如果两个结果都正常但服务还是报磁盘写满那可能是配额或者挂载问题这种情况相对少见后面再单独说。1.2 df -h 和 df -i 一起看才能判断故障类型为了避免你们看到数字就蒙我直接列个对照这是排查时最实用的判断逻辑现象df -hdf -i判断主攻方向典型容量型爆满Use% 高IUse% 正常空间被大文件或日志占满清理大文件和日志隐藏的inode型爆满Use% 不高IUse% 100%小碎文件数量耗尽节点清理大量小文件混合型爆满Use% 高IUse% 高空间和节点都快见底两边都要处理有空间但写入失败Use% 合理IUse% 合理配额、挂载权限、只读等检查挂载参数和配额这表格看着简单实际排查时能帮你省下大把时间。我记得接手过一台机器业务方急吼吼说磁盘快满结果df -h一跑根分区才用了40%df -i一看100%。这就不需要费劲找大文件了方向直接转到到底是谁生成了上百万个碎片文件。1.3 别只盯根分区挂载点结构也要摸清很多服务器的数据盘是单独挂载的比如根分区40G/data单独挂了一块2T的数据盘。如果根分区爆满那问题的严重性远大于数据盘爆满——因为系统进程、临时目录、日志都挤在根分区上根分区满了除了业务挂掉最危险的是ssh都登不进去连排查窗口都给你堵死。所以拿到机器后第一步建议用mount和df -h看一下挂载结构心里有数根分区挂了哪些目录/data、/home、/var这些大目录是独立分区还是和根共用有没有把日志目录、容器数据目录意外挂到容量很小的盘上我见过最典型的案例有人把docker的数据目录默认放在/var/lib/docker结果根分区只有30G镜像一多直接打满。这种就不是清理能根治的得考虑迁移数据目录或者扩容。2. 定位空间去哪了从根目录逐层下钻2.1 du 逐层排查最笨但最可靠的方法确认了是容量型爆满之后下一步就是找哪个目录吃了磁盘空间。这里我不建议一上来就全盘find扫大文件因为全盘扫描速度慢、IO压力大生产环境高峰期跑全盘find无异于自己给自己造故障。正确姿势是逐层下钻用du看每个目录的占用大小du -sh /* 2/dev/null这条命令会把根目录下的各级目录占用列出来。把2/dev/null带上是为了忽略那些没权限读取的目录避免满屏Permission denied刷得你眼花。看到结果后哪个目录大就继续往哪一级钻比如/var大就继续跑du -sh /var/* 2/dev/null逐层往下一般走四五个层级就能把大头锁定。这套方法看着笨实际是排查磁盘占用最稳的手段没有之一。2.2 加个 -x 参数防止跨挂载点绕弯路du下钻的时候很多人容易忽略一个参数-x。它的作用是跳过其他文件系统只看当前挂载点内的目录。什么场景会踩坑假设你根分区40G已经98%了但/data是一个独立挂载的2T数据盘你跑du -sh /data会发现/data占了1.8T。你以为问题在主分区其实/data根本没占根分区的空间。如果你不带-x去全盘统计很容易把独立的大容量磁盘算进来误导排查方向。建议排查时用这个组合du -h -x --max-depth1 / 2/dev/null | sort -hr | head -20-x只统计根分区自身--max-depth1只展示一层目录sort -hr按人类可读的大小倒序排列。这样一眼就能看到是/var还是/usr还是/home在作妖。2.3 用 find 快速揪出超大文件目录定位之后还需要精确找到是哪些文件占的地方。一条比较实用的命令是按大小查找find / -xdev -type f -size 100M -exec ls -lh {} \; 2/dev/null拆解一下参数思路-xdev和du的-x一个作用不跨文件系统防止把数据盘的大文件也算进来-type f只找普通文件不列目录-size 100M找超过100M的文件这个阈值可以自己调-exec ls -lh {} \;把找到的文件以易读的方式列出来带大小和路径跑完基本就能看到一个大文件清单比如-rw-r----- 1 root adm 1.2G /var/log/syslog.1 -rw-r--r-- 1 root root 2.1G /var/log/nginx/access.log -rw------- 1 root root 3.5G /var/lib/docker/containers/xxx-json.log drwx------ 2 root root 8.6G /var/cache/apt/archives看到这几个路径你大概就有数了日志、容器输出、软件包缓存基本都是这些。3. 老生常谈的重灾区日志、容器和缓存3.1 journald日志systemd的隐形硬盘杀手现代主流发行版都用systemd而systemd自带一个日志服务journald它会把系统日志以二进制形式写入/var/log/journal目录。这个目录的坑在于它默认不会无限制膨胀但实际生产环境中日志量大的时候真的能把磁盘吃到见底。查看journald占用journalctl --disk-usage比如输出Archived and active journals take up 3.8G on disk.3.8G听起来不多但在根分区只有40G的云主机上这就是接近10%的份额。清掉它有两种思路一种是直接清理一种是限长。直接清理到指定大小journalctl --vacuum-size200M这条命令会把日志总量收缩到200M以内只保留最近的日志。另一种清理方式是按时间保留journalctl --vacuum-time7d只保留最近7天的日志更早的全部清理掉。生产环境我建议用--vacuum-time7d因为按大小清理可能把近期重要日志删掉按时间保留更有把握。但清理只是治标想治本还得改配置文件。编辑/etc/systemd/journald.conf找到或新增SystemMaxUse200M设置journald最大占用200M存满了就自动滚动覆盖旧日志。改完重启服务systemctl restart systemd-journald这里有个细节SystemMaxUse200M是最多用200M并不是立刻把现有日志压到200M所以重启后还要手动vacuum一次才能立竿见影。这个参数我在多台机器上验证过从源头控制再也不担心journald悄悄把根分区吃光。3.2 大文件清理最佳实践用 truncate 而不是 rm排查大文件时经常能看到这类日志文件-rw-r--r-- 1 root root 2.1G /var/log/nginx/access.log很多人第一反应是rm -f access.log然后发现磁盘使用率没降下来或者nginx开始报错。这就是典型的文件被删除但空间未释放——因为一个进程还开着这个文件的文件句柄rm只是把目录里的文件名删掉但进程仍占用这个文件磁盘空间要等进程关闭句柄才释放。处理正在写入的日志文件正确做法是清空而不是删除truncate -s 0 /var/log/nginx/access.log或者用更经典的方式 /var/log/nginx/access.log这两种方式都是把文件内容清空但文件inode不变打开该文件的进程不会受影响空间立刻释放服务正常写入。这么说吧我处理过太多因为rm日志导致服务写异常的案例尤其nginx、tomcat这类带日志句柄的程序最容易踩坑。除非你确定应用会定期重开日志文件比如logrotate的copytruncate模式否则一律用truncate。3.3 Docker容器日志json.log文件无限膨胀如果你的服务跑在docker里磁盘爆满的头号嫌疑人基本就是容器日志。默认情况下docker用json-file日志驱动每个容器的标准输出都会被写进一个json.log文件路径在/var/lib/docker/containers/container-id/container-id-json.log只要容器持续打印日志这个文件就会一直涨最离谱的案例我见过单个容器日志撑到几十个G直接把系统盘打爆。定位方式du -sh /var/lib/docker/containers/*/*-json.log 2/dev/null | sort -hr | head清理方式即时生效的做法truncate -s 0 /var/lib/docker/containers/xxx-json.log也可以直接删掉这个文件docker会重新创建但删除可能带来短暂的服务日志写入中断所以建议还是用truncate。想根治这个问题得在docker启动参数或daemon.json里加上日志轮转配置。编辑/etc/docker/daemon.json{ log-driver: json-file, log-opts: { max-size: 100m, max-file: 5 } }含义是单个日志文件最大100M最多保留5个超出自动滚动。改完重启dockersystemctl restart docker需要特别提醒修改daemon.json后新建容器才生效已经存在的容器不会自动应用新配置要重建容器才有效。如果你不想重建容器只能定期手动truncate或者写个shell脚本定时清理。3.4 包管理器缓存也和临时文件清理时容易被漏掉yum和apt都会把下载过的软件包缓存到本地。时间久了这些缓存能积累到几个G甚至十几G。清理命令很简单# CentOS/RHEL系 yum clean all # Debian/Ubuntu系 apt clean除了软件包缓存/tmp和/var/tmp这些临时目录也经常潜伏大文件。之前见过有人把临时解压的数据库备份包放在/tmp下几个G就这么躺在那里吃空间。清理时顺便看一眼du -sh /tmp /var/tmp 2/dev/null这里有个小坑/tmp下偶尔会有正在被进程使用的文件直接rm可能影响运行中程序稳妥起见可以参考lsof确认无进程占用后再删。4. 隐藏的磁盘杀手已删除但未释放的空间4.1 这种假清理为什么会发生我接手过一起故障用户运维说我已经删了10G日志了磁盘还是99%。登上去一看df -h确实还是99%但按目录统计的du -sh /汇总下来怎么算都算不出那99%的去向。这种典型的空间消失了场景基本就是文件被删除但仍有进程持有它的文件句柄。日志文件、sqlite数据库文件、临时缓存文件都很容易变成这种孤儿文件。产生原理很简单Linux下rm只是解除文件名的链接如果某进程已经打开该文件这个文件的内容仍会留在磁盘上直到进程关闭文件句柄或进程退出。这类空间不归任何目录管所以du统计不到但df能真实反映出来。4.2 用lsof揪出未释放的文件排查命令lsof L1L1表示显示所有link count小于1的文件也就是那些已经被删除但仍有进程打开的文件。输出里会看到类似COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME nginx 123 root txt REG 253,0 2097152 123456 /var/log/nginx/access.log (deleted)看到(deleted)标识就说明这个文件已经被删过了但进程没释放占着的空间也不会归还。定位到是哪个进程占用后处理方式取决于你是否能接受该进程重启如果只是nginx这类可以让它重新打开日志的服务重启或reload就能释放如果是不能停的关键进程记录PID等待业务低峰期再处理如果有多个文件被占用一条命令快速看全部情况lsof L1 | awk {print $1, $2, $4, $7, $10} | sort -k4 -rh | head -20按SIZE/OFF倒序排列优先处理占用空间最大的几个文件。这个方法我建议在目录大小正常但磁盘使用率异常高的场景优先使用能节省大量无用排查时间。4.3 空间释放后还要确认服务是否受影响删完文件或杀掉占用进程后你以为就完事了还得回头验证一下系统是否恢复正常df -h看使用率是否降下来。同时观察业务进程确认没有因为文件被清理而出现异常。如果是数据库、消息队列这类高依赖文件的进程尤其要谨慎最好选业务低峰期操作。5. inode耗尽的另类困境空间还有就是写不进去5.1 什么场景最容易耗尽inode回到开头提到的df -i。inode耗尽的场景没有空间爆满那么频繁但一旦发生症状很隐蔽——你df -h看还有空间但创建文件、写入日志一直报No space left on device。我列几个最容易产生海量小文件的场景邮件队列Postfix、Exim等邮件服务处理大量队列文件session目录PHP、Java应用的session文件堆积消息队列RabbitMQ、Beanstalkd等未消费消息残留临时目录/tmp、/var/tmp持续写入大量小文件监控和采集agent采集器每秒钟生成一个指标文件Docker容器容器内频繁创建小文件又删除导致inode碎片化5.2 排查inode大户的基本流程先确认是不是inode问题df -i看到IUse%超过90%、甚至100%基本实锤。然后找出哪个目录inode占用最多。注意du是按字节统计大小对inode统计无能为力。要找大量小文件得用find配合计数。逐层下钻的思路是一样的for dir in /*; do echo -n $dir: ; find $dir -xdev -type f 2/dev/null | wc -l; done这个命令会把根目录下每个一级目录的文件数量统计出来。哪个目录文件数最多继续下钻for dir in /var/*; do echo -n $dir: ; find $dir -xdev -type f 2/dev/null | wc -l; done逐层定位到具体目录后查看里面的内容确认能否清理。清理时优先清掉临时文件和过期队列数据不要一上来就rm大目录。这种场景最怕的是批量删文件时操作不当把系统或业务文件误删。删除前至少先确认清楚目录用途。5.3 临时应急和长期方案临时应急除了手动清理还可以给特定目录挂载一个更大的独立文件系统以便让它不再占用根分区的inode。比如把/home下的某个小文件目录单独挂到一个有更多inode的磁盘上mount /dev/sdb1 /var/spool/postfix这个操作需要改/etc/fstab确保重启后依然生效。这种方式适合根分区inode不够但数据盘有大量富余的场景。从长计议更应该关注根源优化应用逻辑定期清理session和临时缓存加日志轮转。如果服务本身特性就是会产生海量小文件建议干脆把该目录指向独立的大inode分区从结构上规避。6. 动手清理前这些安全细节请收好6.1 清理前必须做的事快照和备份的意识很多人一上来就想删但生产环境的清理动作有两条铁律必须刻在脑子里第一激活云厂商的快照功能。云主机通常都支持创建磁盘快照花一两分钟建一个快照万一删错东西还能秒回滚。本地虚拟机也一样先做个快照再动手这是所有操作的保险绳。第二用du和ls -lh把即将删除的文件列出来眼睛过一遍确认没有业务依赖再动手。尤其是那种你自己没部署过的目录一定要先搞清楚是什么应用产生的别直接删。6.2 推荐的清理优先级和命令组合我通常按这个顺序处理效率高且相对安全清包管理器缓存yum clean all或apt clean清journald日志journalctl --vacuum-time7d清理容器日志truncate -s 0各json.log清理业务日志优先logrotate轮转其次truncate清理临时文件确认无进程占用后删除/tmp下的旧文件清大文件find命令找出逐个确认后删除或归档最后清理已删除未释放的进程lsof L1找到占用者重启或kill这套顺序的核心思路是先处理低风险、高确定性的清理项把风险高的动作放在最后执行减少误操作对业务的冲击。6.3 用ncdu等工具提升排查效率如果你觉得命令逐层下钻太累可以装一个可视化工具ncdu。安装很简单yum install -y ncdu # 或 apt install -y ncdu使用也简单ncdu /var进入交互界面后上下键切换目录回车进入d键删除文件q键退出。ncdu的优势是它交互式地展示目录和文件大小可以快速跳转比dufind一步步来高效不少。缺点是初次扫描需要点时间大目录下IO压力有点高生产高峰慎用。6.4 警惕误删系统关键文件的翻车操作这里分享一个我自己踩过坑的细节清理内核相关文件时一定要小心。很多老机器跑久了/boot下面堆积多个旧内核清理旧内核看起来能腾出几百M空间但如果删除仓促、当前内核被误判为旧版本重启直接起不来系统。正确的清理旧内核方式CentOS系用yum autoremoveUbuntu系apt autoremove让包管理器自动识别并清理不在使用的旧内核而不是手动rm。手动rm /boot下的文件相当于自己给自己断后路。另外还要提醒一句云服务器上经常可以看到一些遗留的core dump文件。这类文件是程序崩溃时生成的内存转储可能好几个G。如果确认程序已经不需要排查问题这些core文件可以放心删。7. 别等爆了才救长效监控和预防策略7.1 用cron脚本做磁盘使用率监控救火永远不如防火。我最推荐的方式是在每台服务器上放一个简单的cron脚本定期检查磁盘使用率超过阈值就发告警。脚本不复杂我分享一个我常用的版本#!/bin/bash # 磁盘使用率监控脚本超过90%告警 THRESHOLD90 CURRENT$(df / | awk NR2 {print $5} | tr -d %) if [ $CURRENT -gt $THRESHOLD ]; then echo $(date) 根分区使用率已达 ${CURRENT}%请及时清理 /var/log/disk_alert.log fi保存为/usr/local/bin/disk_check.sh赋执行权限chmod x /usr/local/bin/disk_check.sh然后crontab -e里加一行*/30 * * * * /usr/local/bin/disk_check.sh每半小时检查一次。有条件的可以把告警接到钉钉、企微或者短信接口实现自动化通知。这套方案我用了很久稳定可靠零成本。7.2 全局配置logrotate让日志轮转自动化日志轮转logrotate是Linux自带的日志管理机制大多数发行版默认都装了。问题是默认配置只处理少数几个系统日志像nginx、tomcat这类业务日志一般不包含在内。建议对常用业务日志都加上轮转配置。以nginx为例在/etc/logrotate.d/nginx下写入/var/log/nginx/*.log { daily rotate 14 compress delaycompress missingok notifempty create 0640 nginx adm }参数解读一下daily每天轮转一次rotate 14保留14份旧日志也就是近两周compress旧日志压缩存储delaycompress延迟压缩轮转当日不压缩create轮转后创建新日志文件并设定权限和属主配置完后可以手动验证logrotate -d /etc/logrotate.d/nginx-d是debug模式只打印执行计划不实际执行。确认无误后logrotate会根据cron自动运行默认在/etc/cron.daily里每天自动轮转一次。7.3 Docker环境的日志上限设定防患于未然如果业务大量使用容器我强烈建议在创建容器的时候就指定日志选项。用docker run时docker run --log-opt max-size100m --log-opt max-file5 ...或者更系统地在daemon.json中全局配置前面已经讲过。再补一个细节daemon.json改完要重启docker才生效但如果docker.CONTAINER有现存容器你可以在运行中的容器中通过docker update临时调整吗不行docker update不负责日志选项。所以唯一稳妥的方式是改完配置后把关键容器重建一遍。如果你觉得重建成本高至少把新容器都用上这个参数然后挑低峰期慢慢替换旧容器。7.4 定期巡检把根因挖出来磁盘爆满不是终点只是表症。清理完以后我一般顺手做一次根因复盘问自己三个问题是什么产生的这些文件日志量暴涨业务增长还是监控遗漏为什么没有更早发现监控阈值是不是太高了如何让小问题不再演变成大故障配置是否已经做了上限限制举个实际例子有一次我处理完nginx日志塞满磁盘的问题后顺手查了一下流量统计发现某接口的响应体突然变大了几十倍溯源找到是一个上线版本把日志级别从info调成了debug导致单条日志长度暴增。这个问题如果只停留在清理层面第二天又会爆所幸找到根因后及时收敛了日志级别。所以我的建议是每处理完一次磁盘故障花十分钟做一次原因定位并把应对措施沉淀成脚本、配置或文档。长年积累下来你会发现自己收到的磁盘告警越来越少处理速度越来越快。一些心得结尾从我自己的经验来看磁盘爆满是Linux服务器故障里最好处理但也最容易被低估的一种。说它好处理是因为排查路径相对标准化命令就那么几条按部就班下钻就能定位说它容易被低估是因为很多人处理完第一波清理就撒手不管了结果没过几天又满了然后继续深夜被叫醒。我现在遇到磁盘告警脑子里跑的顺序基本固定先df -h和df -i定位故障类型再du逐层锁定目录再看日志和容器接着lsof排查未释放句柄最后清理加配置上限。整套下来一般不会超过三十分钟如果超过三十分钟还没揪出真凶十有八九是遇到了比较偏门的场景比如特殊应用的数据文件或挂载点问题那就需要结合具体业务再深入。希望这篇内容能帮你少走点弯路至少下次磁盘再红的时候你能多几分底气而不是一身冷汗。如果你有自己的独门排查技巧不妨在评论区记下来互相补补课也挺好。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。