一次磁盘被日志打满的应急处理与长效治理

Cold 发布于 2022-09-17 24 次阅读 585 字 预计阅读时间: 3 分钟 问题排查


早上被告警叫醒:磁盘使用率 95%。磁盘打满是个很阴险的故障——它会影响所有往磁盘写的东西:数据库写不进、日志写不出、服务各种莫名其妙地挂。这篇记一下当天的应急处理和事后治理。

应急:先找到是什么占的

df -h                          # 确认是哪个分区满了
du -h --max-depth=2 / 2>/dev/null | sort -hr | head -20
# 一层层往下钻,最后定位到 /var/log 某应用目录,37G 的日志文件

一个历史遗留的 debug 级日志没关,某接口在高峰期每秒打几百行。找到元凶文件,第一反应 rm 大文件——这里有个经典陷阱要提醒:rm 之后 df 不掉。因为进程还握着这个文件的句柄,空间不会释放,得重启进程才回收。

更优雅的做法是用 truncate 截断,不需要重启进程:

truncate -s 0 app-debug.log    # 或者 : > app-debug.log

如果已经 rm 了怎么办:lsof | grep deleted 找到被删但仍被占用的文件,看情况重启对应进程。另外查被删大文件还有个技巧:lsof +L1 专门列 link count 小于 1 的文件。

十分钟内磁盘从 95% 降到 40%,业务恢复。

长效治理

光删日志是治标,做了三件事治本:

1. logrotate 接管所有应用日志。每个应用一份配置:

/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    missingok
    notifempty
    copytruncate   # 不用重启进程
}

2. 收敛日志级别。debug 级别不进文件是团队规范,那次的遗留配置是三年前某人调试时开的。借这次把所有服务的日志配置模板统一了。

3. 监控要有提前量。告警阈值从 90% 改成 75% 告警、85% 严重。磁盘从 75% 涨到 90% 通常有几天时间,足够你从容处理。另外 systemd 的 journal 也别漏了,journalctl --vacuum-size=500M 限制一下,很多人不知道它默认能吃几十个 G。

留一份"急救卡"

把当天的排查命令整理成一页 cheatsheet 贴在 wiki:df → du 钻取 → lsof 查删除文件 → truncate 截断 → logrotate。故障时人是慌的,有一张能照着敲的卡片比什么都强。

和喜欢的一切在一起~
最后更新于 2022-09-17