运维工作中最常碰到的告警之一就是磁盘空间使用率飙到100%。看似简单的问题,处理不好可能导致服务宕机、数据丢失、日志中断等连锁反应。本文分享一套经过线上验证的标准化处理流程。

应急排查三板斧

第一步:定位大文件与大目录
先用 df -h 确认哪个分区满载,别一上来就全局搜索。然后用 du -sh * | sort -hr | head -10 快速定位当前目录下最大的10个文件/目录。重点关注:

  • /var/log/ 下的日志文件,特别是 syslogmessagesnginx/access.log
  • /var/lib/docker/ 容器镜像和日志(Docker默认不自动轮转)
  • /tmp 临时文件(很多程序异常退出后会留下大文件)

第二步:识别"已删除但未释放"的文件
这是最容易踩的坑:文件被 rm 删除了,但进程还在持有句柄,磁盘空间不会释放。用 lsof | grep deleted 一眼就能看到。这种情况别硬杀进程,先看能不能通过程序自身的日志轮转接口处理,实在不行再优雅重启服务。

第三步:检查隐藏的磁盘占用

  • du -sh .[!.]* 看当前目录下的隐藏文件(很多人会忽略)
  • 检查是否有挂载点被覆盖:比如本来应该挂载到/data的磁盘没挂上,程序直接写到了系统盘的/data目录下
  • 检查lost+found目录:fsck后可能会有恢复的大文件存在这里

根治方案

日志轮转是第一道防线
logrotate 不是配完就完事了,要定期检查是否真的在执行。重点配置:rotate 7(保留7份)、compress(压缩旧日志)、size 100M(超过100M就轮转)。Docker容器日志要单独配,在daemon.json里加 "log-driver": "json-file", "log-opts": {"max-size": "100m", "max-file": "3"}

建立磁盘清理的自动化机制

  • /tmp 目录用 tmpwatch 定期清理超过7天的文件
  • Docker用 docker system prune -af 定期清理未使用的镜像、容器、网络
  • 数据库备份保留策略要明确,别无限累加

监控告警要分层
别等100%了才告警:80%预警(邮件/企业微信)、90%紧急(电话)、95%自动执行清理脚本。预警后给运维留足缓冲时间,别等到业务受影响才动手。

避坑提醒

  • 永远不要 rm -rf 带通配符的路径,先 ls 确认一遍要删的东西
  • 删除前先看文件的修改时间,别把刚生成的业务数据删了
  • MySQL的binlog别直接rm,用PURGE BINARY LOGS命令让MySQL自己清理
  • 清理完一定要 df -h 再确认一遍空间真的释放了

磁盘空间问题看似简单,但每年因为这个导致的线上事故并不少。建立标准化的处理流程,比临时临场发挥靠谱得多。