15 10 月 2026

No space left on device、网站 500、数据库崩、定时任务失败——根因常常就一个:磁盘满了。这篇讲从发现到定位到清理到根治的完整流程,含「删了文件空间不释放」这个经典坑。

需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。

一、三板斧定位

# 1. 哪个分区满了
df -h

# 2. 哪个目录最大(从根开始,两级一级看)
du -h --max-depth=1 / 2>/dev/null | sort -rh | head -10

# 3. 具体是哪些文件
du -h --max-depth=1 /var 2>/dev/null | sort -rh | head

快速锁定大目录的套路:

# 全盘 Top 20 大文件(排除 /proc /sys)
find / -xdev -type f -size +100M 2>/dev/null -exec ls -lh {} \; | awk '{print $5, $9}' | sort -rh | head -20

# 只看最近 7 天变大的目录(新出现的问题源)
find / -xdev -type d -size +500M 2>/dev/null | head

二、重灾区排行榜

按清理收益排序:

排名位置为什么涨清理
1/var/log应用日志无限制增长logrotate(见根治)
2游戏存档/世界玩家多、自动备份多滚动删旧备份
3/var/lib/mysqlbinlog、慢日志设 expire_logs_days
4/tmp、/var/tmp上传残留、会话文件定期清 7 天前的
5旧的 Linux 内核每次升级留一个apt autoremove
6Docker(如装了)镜像/容器/日志层堆积docker system prune
7邮件队列(如装了)退信堆积清 /var/spool/postfix
8面板/网站备份自动备份没清理策略留最近 N 个

针对性命令:

# 日志:看谁最大
du -h /var/log/* 2>/dev/null | sort -rh | head

# 清理 7 天前的压缩日志(安全,current 不动)
find /var/log -name "*.gz" -mtime +7 -delete
find /var/log -name "*.1" -mtime +7 -delete

# MySQL binlog
mysql -e "SHOW BINARY LOGS;"        # 看占用
mysql -e "PURGE BINARY LOGS BEFORE NOW() - INTERVAL 7 DAY;"

# 旧内核(Ubuntu)
sudo apt-get autoremove --purge

# Docker
docker system df                     # 看占用
docker system prune -af --volumes    # 清所有未使用(谨慎:卷也会删)

游戏存档备份的滚动策略:

# 保留最近 14 天的日备份,旧的删
find /backup -name "savegames-*" -mtime +14 -delete

三、经典坑:删了文件空间不释放

rm 了大文件,df 一看空间没变——文件还被进程占着(最常见:日志文件被 nginx/Java 持有句柄,游戏服还在写)。

# 1. 找已删除但被占用的文件
lsof +L1 2>/dev/null | head -20
# 或
ls -l /proc/*/fd 2>/dev/null | grep deleted | head

# 2. 找到占用进程(记下 PID 和文件)
lsof | grep deleted | grep -E "\.log|\.sql"

# 3. 处置:
#    - 日志类:重启服务(或 logrotate 的 copytruncate 模式)
#    - 游戏服:systemctl restart palworld
#    - 不想重启?清空句柄内容:
> /proc/<PID>/fd/<FD号>     # 向被删文件的句柄写空,瞬间释放

根治:日志交给 logrotate 管理,用 create 或 copytruncate 模式,别手动删活动日志。完整配置见Linux 日志管理与 logrotate。

四、根治:三层防线

4.1 logrotate 管日志

sudo tee /etc/logrotate.d/webstack >/dev/null <<'EOF'
/var/log/nginx/*.log /var/log/mysql/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    create 0640 www-data adm
    sharedscripts
    postrotate
        systemctl reload nginx >/dev/null 2>&1 || true
    endscript
}
EOF

4.2 数据库自清理

# my.cnf
[mysqld]
expire_logs_days = 7
max_binlog_size = 256M
slow_query_log = 1
long_query_time = 2

binlog 超过 7 天自动清,慢查询也别无限记。数据库维护全景见MySQL 备份与恢复实战。

4.3 监控告警

# 磁盘 80% 告警(cron 每日)
0 9 * * * df -h | awk '$5+0 > 80 {print $0}' | mail -s "磁盘告警-$(hostname)" admin@example.com

或上监控系统见Prometheus 监控体系,配磁盘使用率曲线,涨势看得见。

巡检模板见服务器日常巡检清单与自动化。

五、应急:磁盘 100% 时先救火

满盘时很多命令都报错,按这个顺序腾空间:

# 1. 最快:清 /tmp 里的垃圾
find /tmp -type f -mtime +1 -delete 2>/dev/null

# 2. 清旧日志压缩包(不动当前日志)
find /var/log -name "*.gz" -mtime +3 -delete 2>/dev/null

# 3. 清包管理器缓存(Ubuntu/Debian 常有几百 MB~G)
apt-get clean

# 4. 数据库 binlog 紧急清
mysql -e "PURGE BINARY LOGS BEFORE NOW() - INTERVAL 1 DAY;"

# 5. 还满?上大杀器:找出刚才没发现的元凶
du -h --max-depth=1 / 2>/dev/null | sort -rh | head -5

腾出空间后别急着干活,先查是谁涨满的——不根治,一周后同样的事再来一遍。

六、磁盘扩容(真的不够用了)

清理到极限还是不够——该扩容了:

# 云盘在线扩容:控制台扩容后,系统内扩展分区和文件系统
lsblk                          # 看新容量是否已生效
sudo growpart /dev/vda 1       # 扩展分区(按实际盘名)
sudo resize2fs /dev/vda1       # ext4 扩展文件系统
# xfs 用: xfs_growfs /data

完整图文流程见Linux 磁盘挂载与扩容实战。


磁盘满是「温水煮青蛙」型故障:不致命但能让全站慢慢瘫痪。记住三板斧(df → du → find)、盯住四大户(日志/数据库/备份/Docker)、配上 logrotate 和告警,这个坑就永远和你无关。

需要现成的游戏云服务器,可以看看财富云计算:一键开服面板,NAT 型无独立公网 IP,价格比独立 IP 机型省一半以上,主流游戏都能快速部署。延伸阅读:云服务器磁盘类型与 IO 性能、僵尸进程与 CPU 异常排查、服务器资源排查实战。

延伸阅读
  1. 网站环境怎么选:LNMP 手动 / 宝塔面板 / Docker / 云开发
  2. 问卷表单系统搭建:SurveyKing / Formbricks,数据自己收
  3. 图床搭建:Lsky Pro / Lychee,自托管图片托管方案
  4. 邮件列表搭建:listmonk 自托管 Newsletter,把读者握在自己手里
  5. 文档站点搭建:MkDocs / VuePress / Docsify,产品文档与技术手册方案
  6. RSS 阅读器搭建:FreshRSS 自托管,把信息流拿回自己手里
  7. 短链接服务搭建:Shlink 自托管,链接数据自己掌握
  8. 网站状态监控页搭建:Uptime Kuma,服务器挂了第一时间知道
更多阅读
  1. 上一篇:钓鱼邮件与社会工程防范:技术之外的最后一道防线
  2. 下一篇:内存泄漏排查实战:从确认泄漏到定位代码到工程化兜底
发表评论 3

取消回复