云服务器磁盘突然爆满怎么办?一套 Linux 磁盘空间排查与清理流程
背景
小规格云服务器(比如华为云 Flexus L 实例,系统盘 40GB 左右)跑久了,经常会遇到“No space left on device”:Docker 拉不动镜像、MySQL 写不进数据、甚至 SSH 登录都变慢。本文整理一套我自己常用的排查顺序,从“哪里满了”到“安全地清掉什么”,每一步都给出命令。
第一步:确认是空间满还是 inode 满
df -h # 看各分区容量使用率
df -i # 看 inode 使用率
如果 df -h 还有空间但 df -i 显示 100%,说明是小文件太多(常见于 session 文件、邮件队列、缓存目录),要找“文件数最多的目录”而不是“最大的目录”:
sudo find / -xdev -type f | cut -d/ -f2-3 | sort | uniq -c | sort -rn | head
第二步:逐层定位大目录
sudo du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -15
sudo du -xh --max-depth=1 /var 2>/dev/null | sort -rh | head -15
-x 表示不跨文件系统,避免把挂载的数据盘、/proc 算进来。一层层往下钻,通常很快能定位到 /var/log、/var/lib/docker 或某个应用的日志目录。装了 ncdu 的话(sudo apt install ncdu),sudo ncdu -x / 交互式浏览更直观。
第三步:查“删了但空间没释放”的文件
一个经典坑:日志文件被 rm 了,但进程还开着它,空间不会释放。
sudo lsof -nP +L1 | grep deleted
找到对应进程后,重启该服务即可释放;如果不能重启,可以直接截断文件句柄:
sudo truncate -s 0 /proc/<PID>/fd/<FD>
以后清理正在写入的日志,用 truncate -s 0 xxx.log 或 : > xxx.log,不要直接 rm。
第四步:常见“大户”的安全清理方式
- systemd 日志:
journalctl --disk-usage
sudo journalctl --vacuum-size=200M
并在 /etc/systemd/journald.conf 里设置 SystemMaxUse=200M,然后 sudo systemctl restart systemd-journald,一劳永逸。
- apt 缓存与旧内核:
sudo apt clean
sudo apt autoremove --purge
- Docker:
docker system df # 先看镜像/容器/卷/构建缓存各占多少
docker image prune -a # 删除未被任何容器使用的镜像
docker builder prune # 清构建缓存
注意 docker volume prune 会删除未挂载的数据卷,里面可能有数据库数据,执行前务必确认。容器日志也可能非常大,可以在 /etc/docker/daemon.json 里限制:
{ "log-driver": "json-file", "log-opts": { "max-size": "50m", "max-file": "3" } }
- 应用日志:用 logrotate 管理,示例 /etc/logrotate.d/myapp:
/opt/myapp/logs/*.log {
daily
rotate 7
compress
missingok
notifempty
copytruncate
}
copytruncate 适合不支持重新打开日志文件的程序。
第五步:加一个简单的预警
与其等爆满再救火,不如加个检查脚本,配合 crontab 或 systemd timer 每小时跑一次:
#!/bin/bash
USAGE=$(df --output=pcent / | tail -1 | tr -dc '0-9')
if [ "$USAGE" -ge 85 ]; then
echo "$(date) 根分区使用率 ${USAGE}%" >> /var/log/disk_alert.log
fi
在华为云上也可以直接用云监控服务(CES)给云服务器配置磁盘使用率告警规则,阈值设 85%,通过短信或邮件通知,比自己写脚本更省心。
小结
排查顺序记住四步:df 看是容量还是 inode → du 逐层定位 → lsof 查已删除未释放 → 针对日志、缓存、Docker 分别清理。再配合日志轮转和监控告警,小磁盘的云服务器也能长期稳定运行。
- 点赞
- 收藏
- 关注作者
评论(0)