半夜两点被磁盘告警消息吵醒,钉钉群里一张截图:某个数据分区 Use% 超过90%,要求立即处理。这种告警我这一两年见过不下几十次,从一开始慌慌张张执行du -sh /*从根目录一层层往下翻,到后来十分钟内锁定根因,中间踩的坑确实不少。最让人崩溃的是这几种情况:df 显示磁盘满了,du 统计出来的目录加起来却差着好几个GB;或者明明把大文件删了,空间却一点没回来;再或者 df -h 看着还有余量,应用却直接报 No space left on device。如果搞不清楚 du、df、inode 以及文件句柄之间的微妙关系,磁盘告警能让你白折腾一整晚。
这里先把结论放前面:磁盘空间告警不等于“删文件”这么简单,我整理了 7 类最容易让运维翻车的高频深坑,每一类都会讲清楚现象、原理、排查命令和处置建议。文中的命令我都在自己的测试机和生产环境验证过,你可以放心照着抄。
1. 磁盘告警后的第一件事:先分清是哪一种“满”
1.1 先跑两条命令:df -h 和 df -i
很多人收到磁盘告警,第一反应就是df -h看一下使用率,然后直接开始找大目录。但这里我建议把df -i也一起跑掉,两条命令输出的信息合在一起,才能判断问题到底是块空间不足,还是 inode 耗尽。
df -h df -i解释一下这两者的区别。df -h看的是文件系统数据块的分配情况,它反映的是“容量还剩多少”;而df -i看的是 inode 的使用情况,inode 可以理解为文件的“户口本”,每个文件或目录都要占用一个。正常情况下 inode 的数量远大于文件数量,不会成为瓶颈,但一旦某个目录下面堆积了海量小文件,就会出现数据块还没用完、inode 已经先耗尽的状况。这时候df -h可能显示还有几十GB,但应用写文件仍然报错,错误信息同样是 No space left on device,非常迷惑。
如果只看容量不看 inode,你会在“磁盘明明没满”的假象里绕很久,或者反过来,在“明明删了一堆文件、容量却不释放”的困惑里白费力气。
1.2 四种告警类型的快速判断
把两条命令的输出拼起来看,基本能判断出问题属于哪一类,这里我列一个自己常用的对照表:
| 现象 | 可能原因 | 下一步方向 |
|---|---|---|
| df -h 满,df -i 正常 | 块空间不足,或有大文件被删未释放 | du 逐层定位,或 lsof 查已删文件 |
| df -h 正常,df -i 满 | inode 耗尽,小文件数量爆炸 | find 统计文件数量,定位小文件目录 |
| df -h 满,df -i 也满 | 双重压力,通常 by 小文件 + 大文件同时堆积 | 先处理 inode,再处理容量 |
| df -h 正常,df -i 正常,仍写不进 | 只读挂载、文件系统错误、配额限制 | mount、dmesg、quota 检查 |
很多监控系统只会画出“磁盘使用率”这一条曲线,不会区分块空间和 inode。所以我处理告警的第一件事,永远是把这两条命令的输出记录下来,和监控数据做一次比对。顺序对了,后面才不会跑偏。
2. 深坑一:df 满了 du 却没满,到底谁在说谎
2.1 为什么 df 和 du 会差出几个 GB
这是磁盘告警里最经典也最容易误导人的一个坑。df 显示一个分区使用了 95%,你用du -sh /或du -x -h --max-depth=1 /把整个目录树统计一遍,发现加起来只有 60%,怎么都对不上。
问题出在统计口径上。df 读取的是文件系统层面的块分配信息,它只关心哪些块已经被标记为“已分配”;du 则是从目录项出发,沿着文件树逐个计算文件大小。正常情况下两者应该接近,差出几个GB也不奇怪,但如果差距达到了几十GB,大概率是有文件已经被 unlink(从目录项里删除),却仍然被某个进程以文件句柄的方式持有。
这个场景在 Linux 里非常常见:应用程序打开了一个很大的日志文件,运维或者清理脚本执行了rm /var/log/app.log,但是 app 进程一直没有重启,日志文件句柄还开着。从文件系统的角度看,这个 inode 仍然“活着”,它占用的数据块没有释放,所以 df 认为空间就是被占着;但从目录项的角度看,文件已经不存在了,du 从根目录遍历时根本看不到它,自然也不会统计。最终结果就是 df 满、du 不满,你删什么都不见效果。
2.2 用 lsof 找出“已经删除但还开着”的文件
定位这种问题的标准命令是 lsof,重点是列出 link count 小于 1 的文件,也就是已经被删除但仍然被进程打开的文件:
lsof +L1这个输出在文件数量很大的服务器上可能会非常多,尤其是一些长时间运行的 Java 应用或数据库进程,可能同时持有几十上百个已删除文件句柄。我一般会加一层过滤,只关心超过 1MB 的已删文件,并按大小排个序:
lsof +L1 2>/dev/null | awk '$7 > 1048576 {print $1, $2, $7, $NF}' | sort -k3 -n这里$7是文件大小,$NF是文件名(通常会显示为path (deleted))。执行完就能看到是哪个进程、哪个文件在占空间。多数情况下,罪魁祸首是应用日志、临时文件,或者数据库的 binlog 之类。拿到进程 PID 后,再用下面的命令确认一下这个进程还在干什么:
ps -p PID -o pid,ppid,etime,cmd确认进程身份之后再做下一步动作,不要急着 kill。
2.3 让空间真正释放的操作顺序
如果确认占空间的进程是日志服务、应用服务这类可以重启的进程,最直接的办法是重启它,重启后文件句柄自动释放,空间就回来了:
systemctl restart app如果进程不能随便重启(比如数据库、消息队列,重启代价很大),并且你确认那个已删除的文件是可以丢弃的日志,还有一种相对温和的清理方式。先找到它在/proc/PID/fd/下的描述符编号:
ls -l /proc/PID/fd/ | grep deleted假设日志文件的 fd 编号是 12,可以这样把它直接清空:
: > /proc/PID/fd/12注意:执行
: > /proc/PID/fd/12之前,一定要确认这个 fd 指向的是日志或临时文件。如果是数据库正在写的数据文件、索引文件或者其他业务关键数据,清空操作等于把数据直接干掉,后果比磁盘告警严重得多。除非你百分百确认文件可以重建,否则不要走这条路。
处理完不要立刻下结论,等一两分钟再执行df -h,确认空间确实回到预期值。如果释放完空间仍然不够用,再继续下一类排查。
3. 深坑二:inode 耗尽,df -h 正常却写不进文件
3.1 inode 到底是什么
先讲一个生活类比。你可以把文件系统想象成一个停车场,数据块就是停车位,而 inode 是每个车位的“登记牌”。当系统存储了大量小文件,每个文件都要占一个 inode,哪怕文件内容只有 1 字节。一旦登记牌发完了,后面的车再有空位也停不进去。反映到应用层面,就是明明磁盘还有空闲容量,但任何新建文件、新建目录的操作都会失败。
inode 中保存的是文件的元数据,包括文件类型、权限、属主、时间戳、硬链接计数,以及指向数据块位置的指针。ls -l看到的大部分属性都来自 inode,而不是文件内容本身。文件系统在格式化时会根据容量和块大小预先分配一批 inode,ext4 通常每 16KB 空间分配一个 inode,但如果实际使用场景以海量小文件为主,这个默认比例很容易被打穿。
3.2 快速定位 inode 消耗大户
先确认 inode 确实满了:
df -i如果看到某个挂载点的 IUse% 达到 100%,接下来要找出是哪个目录“长”出了海量小文件。我常用的方法是按顶层目录统计 inode 数量:
find / -xdev -type f | cut -d/ -f2 | sort | uniq -c | sort -rn-xdev很重要,它让 find 只在当前文件系统内统计,避免跨挂载点把其他分区的文件算进来。输出的第一列是文件数量,第二列是顶层目录名。看到数量异常的那个,再往下钻取:
find /var -xdev -type d -size +100M -exec ls -ld {} \; 2>/dev/null这里的思路是通过目录大小定位小文件密集的目录,不过更实用的还是直接按目录递归统计文件数量,比如:
for d in /var /tmp /home /usr /data; do echo "$d: $(find $d -xdev -type f 2>/dev/null | wc -l) files"; done实战中 inode 耗尽的高发场景很固定:/tmp下垃圾会话文件堆积、邮件队列/var/spool/clientmqueue堵塞、PHP 或 Java 应用的 session 临时文件没清理、容器内频繁产生的小缓存文件。顺着这些目录优先查,命中率很高。
3.3 清理策略和预防手段
找到小文件密集目录后,清理命令按时间条件走,避免一口气全删:
find /var/spool/something -type f -mtime +7 -delete find /tmp -type f -mtime +3 -delete如果要删除的文件数量是百万级的,find -delete可能比较慢,可以先统计数量再批量删,也可以用rsync的--delete配合空目录来做“镜像删除”,但后者更考验细节,普通场景不建议。
预防 inode 耗尽,比清理更重要的几点:一是给日志和临时目录配置轮转(logrotate 或定时任务);二是尽量把大量小文件落到 xfs 文件系统而不是 ext4 上,xfs 的 inode 是动态分配的,默认不容易出现“inode 满了但空间还有”的窘境;三是对业务产生的临时文件设置定期清理任务,不要依赖手工。
注意:ext4 的 inode 数量在格式化时就已经确定,在线扩容文件系统大小时也不会自动等比增加 inode。如果在 ext4 上已经频繁遇到 inode 耗尽,要么删除大量小文件,要么在迁移数据后重新用
mkfs.ext4 -i的合适参数格式化。
4. 深坑三:已删文件不释放,kill 进程不是唯一解法
4.1 文件删了空间为什么不回来
这个坑在很多新人那里一踩一个准:看到磁盘满了,执行rm -rf删掉一个大文件,再df -h,发现空间居然一点没变。紧跟着就会得出“rm 无效”的错误判断。
真实情况不是 rm 无效,而是删除动作只做了“拆目录项”这一步。Linux 的 unlink 机制是这样的:一个文件在磁盘上同时存在两个层面的引用,一个是目录项(dentry),一个是 inode 引用计数。rm会把目录项移除,inode 引用计数减一。如果这个引用计数还有进程通过文件描述符持有,那么 inode 本身不会被回收,数据块也继续处于分配状态。只有引用计数归零,文件占用的空间才会被真正放回空闲块池。
这也是为什么“已删文件不释放”几乎总是和“进程没有重启”绑定在一起。删文件本身没错,错的是文件被某个活着的进程一直咬着不放。
4.2 杀进程还是重启服务,先算代价
找到占用已删文件句柄的进程之后,常见的做法是kill -9,但我的建议是别急着动手。先把代价算清楚:
| 进程类型 | 推荐操作 | 风险说明 |
|---|---|---|
| 普通无状态应用 | systemctl restart app | 风险低 |
| 日志服务、打印服务 | 重启或清空 fd | 有短暂中断窗口 |
| 数据库(MySQL/PostgreSQL) | 禁止直接 kill,优先清空 fd 或规划维护窗口 | 误操作会丢数据 |
| 消息队列、任务调度 | 评估重启窗口,尽量停机处理 | 可能中断消费 |
对于数据库这类进程,如果被删的文件实际上是数据库数据文件或 WAL/binlog,直接 kill 或者清空 fd 都可能造成实例不可用甚至数据丢失。正确的做法是先确认这个文件确实没用,或者马上执行恢复操作,再考虑清理。磁盘告警再紧急,也不能拿数据完整性去赌。
4.3 生产环境里的优雅处理方式
如果是一个可以丢弃的日志文件被应用的 fd 持有,而且应用不能重启,我通常用下面这套流程:
第一步,找到 PID 和被删文件的 fd 号:
lsof +L1 | grep deleted ls -l /proc/PID/fd/ | grep deleted第二步,确认 fd 指向的文件可以清空后,执行:
: > /proc/PID/fd/文件描述符编号执行后 fd 仍然有效,进程可以继续向文件写入,但文件大小已经变成 0,原来占用的数据块全部释放。这种方式的优点是不需要中断业务,缺点是清空后那个文件就真的“没历史”了,如果后面需要排查日志内容,只能从执行时间点之后重新积累。
清空之后等一会儿再看df -h。如果空间还没回来,检查一下是不是多个进程同时持有了同一个已删文件的句柄,这种情况在 fork 出来的子进程里很常见,必须把所有持有句柄的进程都处理掉。
注意:不要在未确认文件用途时对所有 deleted 文件统一执行清空操作。有的程序会把 pid 文件、socket 文件临时 unlink 后重建,这类 fd 并不占多少空间,清空反而可能干扰业务逻辑。只处理明显是日志或大文件的那几个。
5. 深坑四:挂载点掩盖,让你在错误的方向上白忙
5.1 挂载点掩盖是怎么发生的
还有一种情况,df 显示某个分区使用率很高,你在对应目录下跑du -sh /*时,进入一个子目录后看到的容量却来自另一个文件系统。这个现象叫挂载点掩盖。
展开说就是:Linux 允许把一个分区挂载到任意一个空目录上,这个目录就会成为挂载点。假设你的根分区是/,容量 50G,使用率 90%;同时/var/lib/docker独立挂载了一块 500G 的数据盘,使用率只有 1%。如果你执行du -sh /var/lib/docker,它统计的是 500G 数据盘上的文件,不是根分区上的文件,数字可能很小;但如果你对/var做du -sh /var,而/var/lib/docker这个挂载点下面数据很多,它也会被一并统计进来,导致你以为问题出在/var,折腾半天才发现数据根本不在根分区。
反过来还有一种更隐蔽的情况:一个目录本来存放了重要数据,后来因为某个误操作,把一个新分区挂载到了这个目录上,旧文件并没有消失,只是被“盖住”了,df 和 du 都看不到它们。这种场景常见于容器挂载卷、临时挂载盘等,处理时一定要谨慎,避免误格式化。
5.2 用 findmnt 看真实的挂载布局
排查磁盘容量前,我建议先看挂载树,而不是直接照着目录名往下找。findmnt比mount输出更清晰:
findmnt -R /它会以树形格式展示所有挂载点之间的父子关系,一眼就能看出哪个目录是独立分区。如果只想确认某一个目录:
findmnt /var/lib/docker输出会显示这个目录挂载的是哪个设备,挂载参数是什么。配合df -hT 目录路径可以快速知道这个目录消耗的是哪个分区的容量。
5.3 排查时千万别被目录名带偏
把挂载布局理清之后,再使用 du 时建议养成加-x参数的习惯,让统计范围锁定在当前文件系统:
du -x -h --max-depth=1 / 2>/dev/null | sort -rh | head -20-x参数的含义是跳过其他文件系统的子目录,这样即使/data/mysql下面挂了一块很大的独立盘,也不会干扰你对根分区的判断。
出现告警时,我自己的排查顺序是先df -h确认是哪个挂载点,再findmnt看清它下面有没有子挂载,最后才用 du 带着-x去定位目录。这个过程看起来多了一步,却能省掉后面几次无用功。
6. 深坑五:稀疏文件和保留块也在偷走容量
6.1 稀疏文件:ls 和 du 的“数字幻觉”
稀疏文件不是一个故障,但它会制造一种数字上的矛盾,让磁盘排查变得很拧巴。所谓稀疏文件,是指文件逻辑上很大,但实际只占用了少量数据块的文件。最典型的就是虚拟机的虚拟磁盘镜像(qcow2)、数据库预分配但尚未填充的文件、BT 下载的占位文件等。
判断方法很简单,把同一个文件的逻辑大小和实际占用大小对比一下:
du -h --apparent-size 文件路径 du -h 文件路径第一行是逻辑大小(apparent size,类似ls -l看到的文件长度),第二行是实际占领磁盘的块大小。如果两个数字差着几个数量级,就是稀疏文件。
稀疏文件对排查的干扰在于:如果你用du去扫描目录,看到超大文件会以为找到了元凶,但df的使用率却一直没怎么涨,说明这个文件实际上没有吃掉多少空间;相反,如果盲目复制或压缩稀疏文件,复制出来的目标文件可能变成全量数据,瞬间把磁盘占满。处理稀疏文件要么直接用工具(如cp --sparse=always)保留稀疏属性,要么明确判断之后不做处理。
6.2 ext4 保留块:默认被预占的那 5%
ext4 文件系统默认会预留 5% 的数据块给 root 用户,这是文件系统层面的一个保护机制。目的是当普通用户写满磁盘时,系统管理员和系统进程仍然有足够的空间写入关键日志、执行恢复操作,避免系统因为“连一条日志都写不进去”而彻底瘫痪。
不过 5% 这个比例对现代大容量磁盘来说非常“贵”。一块 2TB 的数据盘,5% 就是 100GB。你用df -h看一块 ext4 数据盘时,Size 和 Used、Avail 三个数字加起来往往不等于总容量,中间差出的那一截就是这个保留块。如果你创建的是专门存大文件的数据分区,5% 的保留确实有点浪费。
查看保留块实际大小可以用:
tune2fs -l /dev/sdX | grep -E 'Block count|Reserved block count|Block size'用“保留块数量”乘以“块大小”,就是文件系统被预占的空间。比如 Reserved block count 是 300000,Block size 是 4096,那保留空间就是300000 * 4096 / 1024 / 1024 = 1171MB左右。
6.3 调低保留块比例的正确姿势
如果确认某个分区是数据盘、日志盘,不需要那么高的保留比例,可以用 tune2fs 调整:
tune2fs -m 1 /dev/sdX-m后面的数字是百分比,-m 1表示把保留比例从 5% 降到 1%。要注意的是,这个操作只对 ext2/ext3/ext4 文件系统有效,xfs 没有完全对等的“保留块”概念。系统盘和根分区不建议把保留比例调得太低,尤其当/var/log也位于根分区时,保留空间是关键时刻的最后一道缓冲,调低之后你就要为“日志写满导致系统登录不了”的局面负责。
注意:
tune2fs -m调整保留块不需要卸载文件系统,但为了保险,我还是建议先在非生产环境验证。调整过程中如果出现断电等异常,理论上文件系统仍有变挂的风险,数据盘无事,系统盘建议谨慎。
7. 深坑六:日志、临时文件与 Docker 层堆积
7.1 日志和临时文件的隐藏大户
磁盘使用率在没有任何大文件活动的情况下缓慢爬升,这种“温水煮青蛙”式的告警通常是日志或临时文件堆积。我见过最多的几个位置:
/var/log/journal:journald 默认限制是文件系统容量的 10%,根分区 100G 的情况下,它可以合法占掉 10G。/var/log/下各种应用日志:如果没有配置 logrotate,单条日志文件膨胀到几十 GB 很常见。/tmp和/var/tmp:很多程序生成的临时文件不会自行删除,时间一长数量惊人。- core dump 文件:程序崩溃产生的核心转储,单个文件可能等于进程内存大小,几个 GB 到几十 GB 都有可能。
/var/spool/mqueue:系统邮件队列堵塞时,这里会堆积大量小文件,同时消耗 inode 和块空间。
7.2 Docker 的 overlay2 目录为什么那么占空间
如果你机器上跑了 Docker,磁盘告警时千万记得去看/var/lib/docker。在 overlay2 存储驱动下,镜像层、容器可写层、容器日志都堆在这里。
先用 Docker 自带的分析命令:
docker system df它会显示镜像、容器、本地卷、构建缓存分别占了多少空间。如果镜像和卷都不是大头,再用du看具体位置:
du -sh /var/lib/docker/* du -sh /var/lib/docker/overlay2/*容器日志的位置在/var/lib/docker/containers/容器ID/下,日志文件名一般是容器ID-json.log。很多默认配置下容器日志没有大小上限,一个长期运行的容器日志涨到几十 GB 太常见了。解决办法是在启动容器时加日志轮转参数:
docker run -d --log-opt max-size=50m --log-opt max-file=3 ...更彻底的做法是修改 Docker 守护进程配置,在/etc/docker/daemon.json中加入:
{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" } }然后重启 Docker 让配置生效。这个配置能阻止以后继续产生巨型日志,但已经存在的巨型日志文件还是要手动清理的。
7.3 日志轮转和定期清理的建议
日志文件的规范管理,我认为比“出了问题再清理”重要得多。给日志目录配置 logrotate 是最基本的操作,下面是一个 nginx 日志的配置示例,保存到/etc/logrotate.d/nginx:
/var/log/nginx/*.log { daily rotate 7 missingok notifempty compress delaycompress dateext copytruncate }journald 的占用也要在配置里限一下,修改/etc/systemd/journald.conf:
SystemMaxUse=500M然后重启 journald:
systemctl restart systemd-journald注意:执行
docker system prune时,它会删除所有未被使用的镜像、停止的容器、悬空构建缓存。如果你的同事有依赖旧镜像回滚的习惯,清理前最好先确认一下。更安全的方式是docker system df先看,再单独执行docker image prune -f清理悬空镜像,避免误删。
8. 深坑七:快照和备份造成的“假告警”
8.1 LVM 快照在 df 里看不到,却真实占用空间
我处理过一起非常迷惑的告警:根分区 df 显示使用率从 50% 一路涨到 90%,但进去查看目录总量,一切都很正常。后来才发现,问题根本不在文件系统内部,而是 LVM 快照把卷组的空间吃掉了。
LVM 快照的工作原理是:当宿主逻辑卷(LV)有数据变更时,快照会把变更前的原始数据复制到快照预留区,保证快照里保留的是历史状态。这意味着快照本身会随着数据的持续写入不断增长,最终占满卷组的空闲空间。而 df 看的是文件系统块,根本不会把这个增长反映出来,你只会看到卷组 VFree 越来越少,甚至宿主 LV 将来扩容时无空间可用。
排查命令:
vgs lvs重点看快照 LV 的 Data% 是否接近 100%。确认快照没用了就直接删掉:
lvremove 卷组名/快照名删除快照可以快速释放一大块卷组空间,但这个操作无法回滚,删除前一定要确认这个快照不是恢复数据的最后希望。
8.2 备份工具的隐蔽缓存和挂载点
和快照类似的还有备份工具的“临时文件”。不少备份软件会把数据先写入文件系统上的一个隐藏目录或挂载点,备份完成后再上传到远端,如果中途失败或进程被杀,临时文件就一直留在原地。
这些隐藏目录一般不显眼,名字可能是.snapshot、.backup-cache、.Trash-1000之类。du -sh /时不会默认把这些目录列进*通配里,需要显式检查:
ls -la / du -sh .snapshot 2>/dev/null du -sh .Trash-* 2>/dev/null还有一种情况是备份系统直接挂载了一个外部存储在某个目录下,挂载后该目录的旧数据被掩盖,备份数据持续增长时,你以为占的是当前分区,实际上全部算到了挂载源的存储上。
8.3 快照清理的实战复盘
我之前有个 2TB 数据库卷组,某天监控显示某个逻辑卷的使用率没有明显变化,但整机 df 开始告警,排查进程、删除临时文件都没用。最后是执行vgs才发现卷组 VFree 从 800GB 掉到了不到 50GB,而lvs里一个昨天做备份前自动创建的快照已经膨胀到近 700GB。删掉快照的瞬间,卷组空间就回来了。
从那之后,我给自己定了一个规矩:磁盘告警如果常规排查五分钟没有结论,就顺手跑一遍vgs && lvs,快照占用必须作为一个固定检查项写进排查清单。这比在错误目录里翻半天文件高效得多。
9. 把排查做成习惯:命令组合与速查表
9.1 我的日常排查三件套
以前我收到告警,会敲一堆命令慢慢试。现在基本固定成一套命令组合,五分钟内能完成第一轮定位。
第一步,看容量和 inode,确定是大块空间问题还是小文件问题:
df -hT df -i第二步,从根开始按文件系统边界统计目录大小,排除挂载点干扰:
du -x -h --max-depth=1 / 2>/dev/null | sort -rh | head -20第三步,查已删除但还被进程占用的文件:
lsof +L1 2>/dev/null | awk '$7 > 1048576 {print $1, $2, $7, $NF}' | sort -k3 -n这套组合跑完,大部分告警都能定位到根因。如果结果依然模糊,再检查vgs/lvs快照、journald 日志、Docker 目录。
9.2 磁盘告警排查速查表
把整个排查过程压缩成一张表,几乎可以用来“抄作业”:
| 现象 | 可能原因 | 第一排查命令 |
|---|---|---|
| df -h 使用率高,du 目录总和小 | 已删文件被进程持有 | lsof +L1 |
| df -h 正常,写入仍报 No space | inode 耗尽 | df -i |
| 目录 du 很大,但 df 使用率低 | 该目录有独立挂载点 | findmnt 目录 |
| 单个文件 ls 和 du 差异巨大 | 稀疏文件 | du -h --apparent-size 文件 |
| 使用率缓慢爬升 | 日志、容器日志、core dump | journalctl --disk-usage |
| 所有目录正常,df 仍告警 | LVM 快照或备份缓存占用 | vgs && lvs |
| 删除文件后空间不释放 | 进程句柄未释放 | lsof +L1 | grep deleted |
这张表只是快速入口,真实环境里可能多个因素叠加存在,先按表定位其中一个,处理完以后重新统计,再决定是否继续。
9.3 最后说一条个人经验
磁盘告警处理多了,最深的体会有两条。
一是平时要积累基线数据。我给自己负责的机器准备了一个简单的巡检脚本,每周记录一次各分区 df -h、df -i、top 10 目录、journald 占用这些指标的基线。告警出现时对照基线,哪个数字异常得特别明显,根因就藏在哪里,排查效率完全不一样。
二是每次处理完告警,我都会把“操作了什么、空间回来多少、根因是什么”记到故障复盘文档里。刚开始觉得麻烦,后来发现不同机器的告警原因翻来覆去就是那几类,有了一份自己的案例库,下次再遇到相似问题,几分钟就能给出结论。
希望这篇内容能让你少走几步弯路。磁盘告警不可怕,可怕的是方向错了还一直往前冲。