服务器突然写不进文件,数据库报错,网站 500。第一反应是「磁盘满了」,但真正麻烦的是找出谁占的。
先确认
df -h
看 Use% 和 Avail。如果 / 已经 100%,说明确实满了。还要注意 inode 用尽的情况——磁盘还有空间但写不进新文件:
df -i
IUse% 100% 说明小文件太多,常见于缓存目录、session 文件、邮件队列。
一层层往下找
du -h --max-depth=1 / 2>/dev/null | sort -hr | head -10
进入最大的目录继续:
du -h --max-depth=1 /var 2>/dev/null | sort -hr | head
我这次定位到 /var/log,再往下是某个应用的日志文件:
ls -lhS /var/log/ | head
一个 app.log 20G,从来没轮转过。
已经删了但空间没释放
这是最坑的情况。文件被 rm 掉了,但还有进程持有句柄,空间不会释放:
lsof +L1 | head -20
输出里 SIZE/OFF 很大、NLINK 是 0 的,就是这种。解决办法不是重启机器,而是让进程重新打开文件:
> /proc/<pid>/fd/<fd> # 清空(截断)但不释放句柄
# 或者
systemctl restart 服务名
我遇到过 Nginx 的 access.log 被删了但 worker 还在写,df 一直 100%,du 算出来只有 40G,差值就是那个「幽灵文件」。
常见的大户
- 日志:没配 logrotate,或者配了但没生效(检查
/etc/logrotate.d/) - 数据库:binlog 没清理、慢日志、
ibdata膨胀 - Docker:
/var/lib/docker/overlay2里的镜像层和容器日志 - 备份:本地备份文件堆了几个月
- 缓存:包管理器缓存(
/var/cache/apt、/root/.cache/pip)
Docker 特别容易失控,容器日志默认不限大小:
{
"log-driver": "json-file",
"log-opts": { "max-size": "50m", "max-file": "3" }
}
写进 /etc/docker/daemon.json 后 systemctl restart docker。已经存在的日志要手动清:
truncate -s 0 /var/lib/docker/containers/*/*-json.log
清理的安全顺序
- 日志:先
truncate,不要直接 rm(避免句柄问题) - 包缓存:
apt clean、pip cache purge、docker system prune - 旧备份:按日期删,先
ls确认 - binlog:
PURGE BINARY LOGS BEFORE '2025-01-01'; - 最后才是删业务文件
防复发
- logrotate 配好,按大小 + 按天双条件
- Docker 日志限大小
- 加磁盘告警,80% 就提醒
- 给日志目录单独分区,满了不影响系统盘
磁盘问题几乎都是「没人管」造成的。配好轮转和告警,比事后清理轻松得多。
- THE END -
最后修改:2025年1月11日
非特殊说明,本博所有文章均为博主原创。
如若转载,请注明出处:https://mi-blog.cn/archives/691
共有 0 条评论