凌晨三点的磁盘告警
监控群突然弹出:「/ 使用率 98%」。网站还能跑,但日志写不进去了,上传接口开始报错。这种「磁盘打满」是运维最高频的线上事故之一。好消息是:它有标准排查套路,du / df / lsof 三板斧基本能定位九成问题。
一、先看清:是「真的满」还是「删了还满」
df -h
# 输出示例
# Filesystem Size Used Avail Use% Mounted on
# /dev/vda1 40G 38G 0.5G 98% /
df 看的是文件系统层面的用量。如果 df 说满、但 du 统计的目录大小对不上,多半是被删除但仍在被进程占用的文件(见第三节)。
二、定位「谁占空间」:du 从根往下挖
# 先看各一级目录占用
du -h --max-depth=1 / 2>/dev/null | sort -h
# 钻进最大的目录继续挖
du -h --max-depth=1 /var 2>/dev/null | sort -h
# 找单个大文件(>100M)
find / -type f -size +100M -exec ls -lh {} \; 2>/dev/null
常见真凶排名:
/var/log:没轮转的日志(尤其是 Nginx、Java 应用日志)/var/lib/docker:Docker 镜像/卷/构建缓存堆积- MySQL 的
binlog或慢查询日志 - 无人清理的临时上传目录
三、经典陷阱:文件删了但空间不释放
你 rm 了一个 10G 日志,df 却纹丝不动。原因是还有进程(比如 Nginx、Java)打开着这个文件句柄,磁盘块不会释放。
# 找出「已删除但仍被占用」的文件
lsof +L1 | grep deleted
# 或
lsof | grep deleted
解决方式有两种:
- 重启持有句柄的进程(最快,但会短暂影响服务)。
- 更优雅:让进程重新打开日志。例如 Nginx 用
nginx -s reopen,Java 用日志框架的 reload;或者先:> bigfile.log清空再删。
四、Docker 残留:最容易被忽略的大户
# 查看 Docker 占用的空间明细
docker system df
# 清理:悬空镜像、停止的容器、无用卷(谨慎)
docker system prune -a --volumes
构建缓存和退出但未删除的容器往往吃掉几十 G。定期 prune 立竿见影。
五、止血 + 根治
临时止血:
- 清空最大日志:
:> /var/log/xxx.log(保留文件、清空内容,不破坏句柄持有者) - 删孤立大文件、清理 Docker
根治(避免下次再犯):
- 日志轮转:用
logrotate配置按大小/天切割并保留 N 份。 - 监控告警:磁盘 80% 就告警,别等 98%。
- 应用层限制:上传目录设配额,日志框架限制单文件大小。
logrotate 最小可用配置
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
daily
rotate 7
size 100M
missingok
notifempty
compress
copytruncate
}
小结
磁盘满不可怕,可怕的是没套路乱删。df 看总量、du 找目录、lsof 查幽灵文件,三板斧定位后,用日志轮转和监控把问题消灭在萌芽。把它做成 runbook,下次告警你就能多睡两小时。




