70 lines
6.1 KiB
Markdown
70 lines
6.1 KiB
Markdown
# 2026-09-21 云端磁盘满导致登录卡死排查与修复
|
||
|
||
### 1. 排查云端系统无法打开并解决
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 云端系统现在又异常了,无法打开,检查一下什么原因并解决
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
已完成排查并修复,云端(gyl.dieya.net.cn)访问恢复正常。
|
||
|
||
**现象与时间线**
|
||
|
||
- 09:27 报障时外网探针:静态首页可返回 200,但 `POST /api/login` 会卡住不返回,即页面能打开、点登录没反应。
|
||
- 08:30 每日备份 cron 执行,导出 698M 数据库 SQL 后打包时磁盘写满,日志出现 `gzip: stdout: No space left on device`,`tar` 只写入 2048/10240 字节后失败,本次备份**中断失败**。
|
||
- 因为脚本是 `set -euo pipefail` 且中断在第 2 步,末尾的 `rm -f ${DB_DUMP}` 没执行到,那 698M 临时 SQL 文件滞留在项目目录,磁盘继续维持 100%。
|
||
- 09:05 gunicorn 出现 `Autorestarting worker after current request`,09:07 报 `WORKER TIMEOUT (pid:968880)`,中断栈正好停在 `POST /api/login` → `services/db.py` 的 `conn.commit()`,即 **MySQL 因磁盘满无法提交写入,登录请求被拖到 60 秒超时**。
|
||
- 排查时服务已部分自愈(gunicorn 自动重启,登录接口 0.4 秒返回 401),但磁盘仍是 100%、可用 0,随时会再挂。
|
||
|
||
**根因**
|
||
|
||
- 磁盘 100% 满:40G 用了 38G,可用 0(2 核 2G 的云端小机)。
|
||
- 占空间主要是历次累积的备份:`/opt/dy-dashboard-backups` 12G、`/opt/dy-dashboard_backups` 4.5G、`/opt/dy-dashboard/backups` 3.4G、`/home/ubuntu/dy-dashboard-backups` 3.9G、`/opt/backups` 0.65G、`/home/ubuntu/backups` 0.71G,合计约 25G。
|
||
- 现有自动保留策略只覆盖每日备份目录里的 `dy_platform_backup_*`(30 天),`new_products_images_*` 与各次手工/部署备份目录都没有清理机制。
|
||
- 本次不是代码或数据库问题:MySQL、nginx 日志均无报错,恢复写入后登录、备份全部正常。
|
||
|
||
**处理(清理范围先经旭东确认,选「清理 9/10 之前的旧备份 + 失败残留」)**
|
||
|
||
- 删除各备份目录中 2026-09-10 之前的备份(`/opt/dy-dashboard-backups`、`/opt/dy-dashboard_backups`、`/opt/backups`、`/home/ubuntu/backups`、`/home/ubuntu/dy-dashboard-backups`、`/opt/dy-dashboard/backups`),保留 09-10 以后全部备份。
|
||
- 删除失败残留:698M 临时 SQL `dy_data_20260921_0830.sql`、截断损坏的 `dy_platform_backup_20260921_0830.tar.gz`(仅 85M,不可用)。
|
||
- 未动范围外内容:`/opt/dy-dashboard.old-20260808_101255`(278M)、`/opt/dy-dashboard-before-20260807_092207`(254M)保留;两份 full-cloud 全量备份(09-20、09-21)保留。
|
||
|
||
**结果与验证**
|
||
|
||
- 磁盘:38G 已用 / 0 可用(100%)→ **23G 已用 / 16G 可用(59%)**,释放约 15G。
|
||
- 服务:`dy-dashboard.service` active(gunicorn 主进程未重启过);本机 127.0.0.1:18888 → 200(0.004s);公网首页 200(0.34s)、登录接口 200(0.68s)。
|
||
- 补做备份:重跑 `backup.sh` 成功,生成 `dy_platform_backup_20260921_0930.tar.gz`(177M)+ `new_products_images_20260921_0930.tar.gz`(59M),临时 SQL 由脚本正常清理,磁盘保持 60%。
|
||
|
||
**后续建议(待旭东决定,未擅自改)**
|
||
|
||
- 给手工/部署备份目录加保留策略(例如只留最近 7~14 天),并让 `backup.sh` 的清理覆盖 `new_products_images_*`,否则磁盘还会再次被慢慢填满。
|
||
- `backup.sh` 建议做失败兜底:tar 失败时也要把临时 SQL 删掉(当前 `set -e` 会让 698M 文件残留),并可考虑磁盘水位预检。
|
||
|
||
### 2. 磁盘占用治理建议与每日备份保留策略
|
||
|
||
**旭东 → OpenClaw:**
|
||
|
||
> 查一下现在云服务里面的40g用了多少了?
|
||
>
|
||
> 关于这个磁盘状态占用情况,有没有什么好的建议处理方法?
|
||
|
||
**OpenClaw 响应:**
|
||
|
||
**现状**:40G 用 23G、可用 16G(59%)。占用分布:`/opt/dy-dashboard-backups` 7.0G(两份 full-cloud)、`/var/lib/mysql` 3.0G、`/opt/dy-dashboard` 2.8G、`/var/log` 580M、`/opt/dy-dashboard_backups` 245M。
|
||
|
||
**定位到真正的"水龙头"**:自动化任务「云端每日完整备份」(每天 08:00 跑 `backup_cloud_daily.py`)每天向 `/opt/dy-dashboard-backups` 写一份 3.5G 全量包,**没有任何保留策略**;今天 08:00 那次吃掉最后约 4G(manifest 记录创建时 `disk_free=785M`),08:30 每日备份就写不进去了。按此节奏每日增量约 3.7G,20G 可用只够约 5 天。该全量包 3.4G 中水分极大:脚本 `tar -czf ... -C /opt dy-dashboard` 无任何排除项,把 venv、uploads、vault、logs 连同 `/opt/dy-dashboard/backups` 里的每日备份包又打了一遍包(套娃)。
|
||
|
||
**给出的建议**:① 全量备份瘦身(排除 venv/backups/logs 等,3.4G→约 250M)+ 只留最近 2 份 + 降为每周一次;② 每日备份目录加保留策略;③ `backup.sh` 加失败兜底(trap 删临时 SQL)与磁盘水位预检;④ 全量包定期外移到 11.79 或对象存储,云端只留最近 1 份;⑤ journald 设 `SystemMaxUse=200M`、MySQL 加 `binlog_expire_logs_seconds`、`inventory_detail`(1.1G)历史明细归档;⑥ 加磁盘水位告警(>80% 主动通知)。
|
||
|
||
**旭东选定执行**:仅第 ② 项「每日备份目录加保留策略」。
|
||
|
||
**已执行(云端生产)**:
|
||
|
||
- 先备份原脚本到 `~/dy-backups/backup-sh-pre-retention-20260921_094541/backup.sh`。
|
||
- 修改 `/opt/dy-dashboard/backup.sh` 第 4 步清理段:`dy_platform_backup_*.tar.gz` 保留期 30 天 → **14 天**;新增 `new_products_images_*.tar.gz` **保留 7 天**(此前该文件从未被清理,每天约 59M)。`bash -n` 语法检查通过。
|
||
- 立刻按新策略清理一次:图片包删除 09-10/09-11/09-12/09-13 共 4 份(约 230M),09-14 起 7 份保留;项目包无超过 14 天的,未删除。
|
||
- 目录由 2.8G 降到 2.5G,文件数 21;磁盘 59%(23G 用 / 16G 可用)不变(本次释放量在四舍五入内);服务 active、本机 200。
|
||
- 未执行其余各项:全量备份瘦身/保留/降频、backup.sh 失败兜底、备份外移、系统层优化、磁盘告警,均等旭东后续指令。
|