先说结论:磁盘满先分两种——空间满和 inode 满。空间满看 df -h,inode 满看 df -i;再用 du 找大目录、lsof 找已删除但被占用的文件。清理顺序是日志轮转、临时文件、Docker 垃圾,最后才是扩容。
两个命令先跑:
df -h
df -i
如果 df -h 显示 100%,是空间满;如果空间还有但写入报 “No space left on device”,多半是 inode 满,常见于大量小文件、session、缓存。
找大目录和大文件
du -xh --max-depth=1 / | sort -h
du -xh --max-depth=1 /var | sort -h
find / -xdev -type f -size +500M -printf '%s %p\n' 2>/dev/null | sort -nr | head -20
从根目录一层层往下,先找到最大的目录,再进去重复。常见大户是 /var/log、/var/lib/docker、/var/lib/mysql、网站上传目录、备份目录和临时文件。

日志怎么清
- 先看再删:确认日志还有没有用,别把故障现场删了
- 用 truncate 不用 rm:正在写的文件被 rm 后,空间不会立刻释放
- 配 logrotate:按天/大小轮转,保留 7 到 30 天,压缩归档
- journald 限制:
SystemMaxUse=1G,别让系统日志无限涨
# 清空正在写的日志(保留文件句柄)
: > /var/log/nginx/access.log
# journald 限制
journalctl --vacuum-size=500M

删了文件空间没释放
lsof +L1 | head -20
# 或
lsof | grep deleted | head -20
进程还开着被删除的文件,空间就不会释放。找到 PID 后重启对应服务,或者用 : > /proc/<pid>/fd/<fd> 清空(确认文件类型再操作)。这是“删了 10G 但 df 没变”的最常见原因。
inode 满了怎么办
inode 满通常是大量小文件:session 文件、缓存碎片、邮件队列、没清理的临时文件。找法:
for d in /var /tmp /home; do echo "== $d"; find $d -xdev -type f | cut -d/ -f1-4 | sort | uniq -c | sort -nr | head; done
找到目录后按业务清理,或者把缓存改成单文件/数据库存储,别让几十万个小文件堆在一个目录里。
Docker 占了多少
docker system df
docker image prune -a
docker volume ls
docker system prune --volumes
注意 prune --volumes 会删未使用的数据卷,执行前确认没有数据库和上传文件挂在那里。容器日志也要限制:在 daemon.json 里设 max-size 和 max-file。
扩容怎么做
- 云控制台扩容云盘(先打快照)
- 分区扩容:
growpart /dev/vda 1 - 文件系统扩容:
resize2fs(ext4)或xfs_growfs(xfs) - 确认
df -h已生效
扩容前先确认文件系统类型,xfs 只能扩不能缩。生产环境先快照,再操作分区。

怎么预防
- 监控磁盘使用率和 inode 使用率,80% 告警
- 日志轮转、容器日志限制、临时文件定期清理
- 备份和导出写到对象存储,别堆在本机
- 数据库 binlog 设置保留天数
- 大文件上传先落临时目录,设置生命周期
数据库和容器目录
MySQL 的 binlog、慢日志、错误日志都能把磁盘吃满。binlog 按天保留,设置 expire_logs_days 或 binlog_expire_logs_seconds;慢日志和 general log 不要长期全开。容器目录重点看 overlay2、volumes 和容器日志,日志用 docker logs 查看时也要注意文件大小。
快照和备份别放本机
很多磁盘满是“备份写到了本机”。备份、导出、数据库 dump 都应该写到对象存储或另一台机器,本机只留最近一份,并设置保留天数。快照是云平台的,不占你文件系统,但不能替代可读的备份。
推荐的清理顺序
先删临时文件和过期备份,再轮转日志,再清 Docker 未使用镜像和卷,最后处理数据库 binlog。每清一步都用 df -h 确认,别一次性删太多;不确定的文件先移到临时目录,观察一天再删。
最后,把磁盘和 inode 使用率都设 80% 告警,别等 100% 才处理;每次清理记录释放了多少、清的是什么,方便下次快速判断。
清理前先打快照,尤其是要动数据库目录和上传目录时;误删的恢复成本,远高于多花十分钟确认。
磁盘治理是日常活,不是出事才做,养成每周看一眼的习惯。
,早发现早处理,比事后补救便宜得多。
常见问题 FAQ
Q1:df 显示满了,du 加起来却没那么多?
大概率有已删除但被进程占用的文件,或者挂载点被覆盖。用 lsof +L1 查,再检查挂载。
Q2:能直接 rm 日志吗?
不推荐。正在写的日志被 rm 后空间不释放,进程还在写。用 truncate 或 logrotate。
Q3:inode 怎么清理?
先找到小文件集中的目录,按业务清理;长期方案是改存储方式、加清理任务,或者换支持更多 inode 的文件系统。
Q4:扩容后 df 没变?
只扩了云盘,没扩分区或文件系统。按 growpart → resize2fs/xfs_growfs 的顺序做。
Q5:Docker 的 prune 能随便跑吗?
不能。--volumes 会删未使用卷,可能包含数据库数据。先 docker system df 看清楚。
总结
磁盘满先分空间和 inode,再找大目录、清日志、处理被占用文件、清 Docker 垃圾,最后才扩容。清理前备份,删文件前确认没有进程占用。
需要一台磁盘更宽裕的机器做迁移或扩容验证,可以按小时开一台萤光云香港 CN2 VPS,先把数据同步过去再切换。







