线上机器突然报磁盘告警,登上去却不知道从哪下手,是很多人都有过的经历。其实这类排查有一套固定套路可以复用:先用 df 定位到满的分区,再用 du 逐层下钻目录,最后用 find 把大文件精确抓出来。三板斧之外,还有两个经典坑------文件删了空间不释放、du 和 df 数字对不上------也一并说清楚。
第一步:df 看哪个分区满了
bash
df -h
看 Use% 列,找到 90% 以上的分区(一般是根分区 / 或数据盘 /data)。注意两种特殊情况:
- inode 耗尽 :
df -h显示空间还有,但写入报 No space left on device------执行df -i看 IUse%,大量小文件(如 session 文件、邮件队列)会把 inode 吃光 - overlay / tmpfs 异常:容器环境的 overlay 分区满了,通常对应宿主机 docker 目录
第二步:du 逐层下钻
进入满的分区对应挂载点,从顶层往下找:
bash
cd /
du -sh * 2>/dev/null | sort -rh | head -20
这条命令列出根目录下各目录的大小并按大小排序。2>/dev/null 屏蔽权限报错,sort -rh 让 4.2G / 380M 这样的人类可读数值正确排序。
找到最大的目录后 cd 进去重复执行,一般两三层就能定位到具体业务目录。常见的空间大户:应用日志、临时文件目录、旧版本包备份、/var/log、/var/lib/docker。
df / du / find 的参数细节不少(-x、-xdev、-size 的单位写法、-mtime 的负数用法),我把常用的整理成了一份 Linux 命令速查表放在 dxtool.cn,排查时对着查参数比翻 man 页快。
排除挂载点干扰:如果系统里有 NFS 等网络挂载,du -shx 的 -x 参数可以只统计当前文件系统,避免把挂载盘算进来。
第三步:find 精确抓大文件
知道目录了,最后一步找出具体是哪些文件:
bash
# 当前目录下找出大于 500MB 的文件,按大小列出
find /var/log -type f -size +500M -exec ls -lh {} \;
# 找出 7 天内修改过且大于 100MB 的文件(最近活跃的大文件优先处理)
find / -xdev -type f -size +100M -mtime -7 -exec ls -lh {} \; 2>/dev/null
# 找出最大的 20 个文件(xargs 配合 du 汇总排序)
find / -xdev -type f -print0 2>/dev/null | xargs -0 du -h 2>/dev/null | sort -rh | head -20
处理文件时优先考虑「删旧 + 截断」:
bash
# 日志类大文件:清空而不是删除(避免进程句柄问题,见下文坑一)
truncate -s 0 app.log
# 已压缩的历史日志直接删
rm /var/log/app/app-2025-*.gz
坑一:文件删了,空间没释放
rm 掉大日志后 df -h 纹丝不动?文件被进程持有句柄时,删除只是断开目录项,数据块要等进程关闭文件才释放:
bash
# 找出已被删除但仍被占用的文件
lsof +L1 | sort -k7 -rh | head
# 处理方式:重启对应进程;或对日志类先 truncate 再 rm
truncate -s 0 /var/log/app/app.log
所以生产环境清理日志的正确姿势是 truncate 清空,而不是直接 rm。
坑二:du 和 df 数字对不上
du 统计的总量远小于 df 显示的已用空间,除了坑一的句柄问题,还有一种可能是文件被删除时正处于挂载点之下------先卸载或移开挂载点再排查挂载目录下的残留文件。
治本建议
- 日志轮转:logrotate 配置按天切割 + 保留 7~15 天
- 业务临时文件定时清理脚本 + cron
- 磁盘告警阈值设两档:80% 预警、90% 告警,留出处理时间
日常用到的文件查找、日志处理命令,都可以在 dxtool.cn 的 Linux 命令速查表里对照。站内的文本对比、JSON 格式化等工具是纯离线的,排查配置类问题时顺手能用。
本文同步发布于 dxtool.cn