提交 97198373 authored 作者: 陈泽健's avatar 陈泽健

docs(自动化部署): ujava2 脚本死锁问题处理与 fastdfs 临时目录分析报告

上级 baa815f5
# HANDOFF — 自动化部署脚本会话交接文档
> **生成时间**:2026-09-01
> **会话主题**:新统一平台 ujava2-startup.sh 定时脚本 flock 死锁导致日志停止排查与修复
> **最近更新**:2026-09-01(首次创建,记录 ujava2 脚本死锁修复闭环:服务器脚本 3 处修复 + 死锁释放 + cron 自动恢复验证 + 问题处理/计划执行双文档)
---
## 任务概述
围绕新统一平台(192.168.5.70)定时脚本 `ujava2-startup.sh` 完成以下工作:
1. 排查 `ujava2-service-manager.log` 服务日志自 13:26 后停止更新的根因
2. 确认 crontab 每 3 分钟触发但日志每 3 分钟打印「另一个实例正在运行,退出」
3. 定位根因:后台守护进程 malan 继承 flock 锁 fd(fd 200)导致死锁永久占锁
4. 从源头修复服务器部署脚本(与本地仓库脚本对齐)
5. 释放当前死锁,验证 cron 自动恢复
6. 产出问题处理文档 + 计划执行文档
---
## 已完成事项
| # | 产出项 | 位置/路径 | 说明 |
|---|--------|-----------|------|
| 1 | 根因定位 | 服务器 192.168.5.70 `/data/services/scripts/ujava2-startup.sh` | 后台子进程继承 flock 锁:`start_malan_service` 执行 `bash -c "source /etc/profile && ./malan" &` 启动的 malan(PID 70515)继承 fd 200 → 常驻守护进程永不退出 → 锁永久占用 |
| 2 | 证据链确认 | `/var/log/ujava2-cron.log` + `/proc/70515/fd` + `fuser -v` | cron 日志 13:27 起每 3 分钟「另一个实例正在运行」;`ls -la /proc/70515/fd \| grep 200``200 -> /tmp/ujava2-startup.lock`;malan 启动时间 13:26:00 与用户确认的"自动化部署完毕"吻合 |
| 3 | 备份服务器脚本 | `/data/services/scripts/ujava2-startup.sh.bak.20260901` | 修复前备份,md5 `41149bfec4622d4354348383e46bab89` |
| 4 | 修复1 - start_malan_service 关闭锁 fd | 服务器脚本 | `bash -c "... ./malan" &` 前加 `exec 200>&-` + 注释「关闭锁文件描述符,防止子进程继承导致锁无法释放」(与仓库版一致) |
| 5 | 修复2 - restart_host_extapi_service 关闭锁 fd | 服务器脚本 | `bash -c "... ./run.sh" &` 前同样加 `exec 200>&-`(消除 host extapi 路径同类隐患) |
| 6 | 修复3 - LOG_FILE 定义前置 | 服务器脚本 | `LOG_FILE` 移至 flock 之前 + `mkdir -p "$(dirname "$LOG_FILE")"`,修复 `tee: '': 没有那个文件或目录`(部署旧版缺陷) |
| 7 | 语法校验 | 服务器脚本 | `bash -n` 通过(SYNTAX_OK) |
| 8 | 释放死锁 | 服务器 | kill 持锁旧 malan(PID 70515),脚本自动拉起新 malan(PID 128794) |
| 9 | 手动执行验证 | 服务器 | 修复后脚本 EXIT_CODE=0,完整跑通 API 检查、服务自愈、6060 监测;新 malan 不再持有锁 |
| 10 | cron 自动恢复验证 | 服务器 | 15:51、15:54 两轮 cron 日志正常完整执行(`6060端口正在监听`),无 WARNING 退出,锁执行完毕后自动释放 |
| 11 | 问题处理文档 | `Docs/PRD/自动化部署脚本/新统一平台/问题处理/_PRD_ujava2脚本死锁导致日志停止_问题处理.md` | 2026-09-01 创建:背景/现象(4 类信号)/根因/涉及文件/代码验证/解决方案/预防措施/问题状态;已随 commit `1e8018f7` 提交推送 develop |
| 12 | 计划执行文档 | `Docs/PRD/自动化部署脚本/新统一平台/问题处理/_PRD_ujava2脚本死锁导致日志停止_问题处理_计划执行.md` | 2026-09-01 创建:问题分析/修复方案(3 处变更)/执行计划 9 步全 [x]/验证结果/回滚方案/优化功能回填;已随 commit `1e8018f7` 提交推送 develop |
### 验证结果
```
# 根因证据(修复前)
fuser -v /tmp/ujava2-startup.lock
root 70515 F.... malan ← ./malan 守护进程持有锁
ls -la /proc/70515/fd | grep 200
l-wx------ 1 root root 64 ... 200 -> /tmp/ujava2-startup.lock
ps -o pid,lstart,cmd -p 70515 → STARTED: Tue Sep 1 13:26:00 2026 ./malan
# 修复后验证
bash -n ujava2-startup.sh → SYNTAX_OK
手动执行脚本 → EXIT_CODE=0,完整跑通
新 malan PID 128794 → 不再持有 /tmp/ujava2-startup.lock
cron 15:51 / 15:54 两轮 → 日志正常完整执行,无「另一个实例正在运行」
fuser /tmp/ujava2-startup.lock → 运行间隙无输出(锁自动释放)
cron 日志 → 无 tee: '' 报错
```
---
## 当前阻塞项
| 类型 | 描述 | 原因 |
|------|------|------|
| 待办 | 仓库脚本与服务器脚本完全对齐(含 `RETRY_INTERVAL` 20 vs 30、`stop_service` kill 逻辑差异确认) | 服务器部署的是旧版脚本;本次已回填缺失的三处修复(exec 200>&- ×2 + LOG_FILE 前置),剩余差异为既有配置差异,非本次死锁问题范围,尚未对齐 |
| 信息 | 仓库工作区存在 `.claude/skills/DM8-PROCESS/code/` 等大量文件删除记录 | 历史遗留状态(Git 状态快照),与本次会话无关,未纳入提交 |
无其他阻塞,本次死锁问题已闭环。
---
## 下一步计划
| # | 步骤 | 预期结果 |
|---|------|----------|
| 1 | (可选)按正常部署流程将仓库脚本重新部署到服务器 | 确保服务器部署版与仓库脚本(source of truth)完全一致,避免部署版本再次落后 |
| 2 | (可选)确认 `RETRY_INTERVAL` 20/30 与 `stop_service` kill 逻辑的最终配置差异 | 决定以仓库版为准还是服务器版为准,完成完全对齐 |
| 3 | (待确认)提交本 HANDOFF | 两份 PRD 文档已由 commit `1e8018f7` 提交推送;本 HANDOFF 为新建文件,尚未 commit/推送(待用户确认) |
| 4 | (可选)处理 `.claude/skills/DM8-PROCESS/code/` 等遗留删除记录 | 确认是否需提交,避免工作区长期带未提交状态 |
---
## ⚠️ 踩坑警示 — 绝对不要再踩
1.**脚本内用 `flock` 加锁后再 `&` 后台启动守护进程,必须先在启动前 `exec 200>&-` 关闭锁 fd** — 本次死锁直接根因:`start_malan_service`/`restart_host_extapi_service` 后台启动 malan/run.sh 时未关闭 fd 200,子进程继承 flock 锁;malan 为常驻守护进程永不退出 → 锁永久占用 → 此后所有 cron 触发 `flock -n` 失败,主流程(API 检查/服务检查/自愈/6060 监测)全部不再执行,表现为「服务日志停止更新」。排查脚本日志停止问题优先查:`fuser -v /tmp/ujava2-startup.lock` 与 cron 日志 `/var/log/ujava2-cron.log` 最后几行(比服务日志更能反映脚本真实状态)。
2.**定时脚本中 `LOG_FILE` 必须定义在 flock 代码块之前** — 部署旧版把 `LOG_FILE` 定义在 flock 之后,flock 分支先执行时 `$LOG_FILE` 为空 → `tee -a ""``tee: '': 没有那个文件或目录`。新增定时脚本统一模板:`LOG_FILE` 前置 + `mkdir -p "$(dirname "$LOG_FILE")"`
3.**服务器部署脚本事后必须与仓库脚本 diff 对齐** — 本次发现服务器部署版落后于仓库版(缺三处修复),本地仓库脚本才是 source of truth。部署流程应校验差异,避免部署版本带旧缺陷上线。
4.**不要用 `git add .` 或 `git add -A`** — 本仓库规范要求逐文件 add,避免把无关的历史删除/新增文件夹带进提交(当前工作区已有 `.claude/skills` 大量删除记录,务必逐文件核对)。
---
## 附录:关键文件/资源链接
| 资源类型 | 位置 | 备注 |
|----------|------|------|
| 仓库脚本(source of truth) | `自动化部署脚本/x86架构/新统一平台/定时脚本/ujava2-startup.sh` | 已含全部修复(exec 200>&- ×2 + LOG_FILE 前置),本地 497 行,md5 `51dac896d04c32af397d532a0f365489` |
| 服务器部署脚本 | 192.168.5.70 `/data/services/scripts/ujava2-startup.sh` | 修复后 md5 `ab246c190061121ea0846a84f453edd6`,本地 495 行 |
| 修复前备份 | 192.168.5.70 `/data/services/scripts/ujava2-startup.sh.bak.20260901` | md5 `41149bfec4622d4354348383e46bab89` |
| flock 锁文件 | 192.168.5.70 `/tmp/ujava2-startup.lock` | 已被新 malan 释放,cron 运行间隙无持锁进程 |
| 服务日志 | 192.168.5.70 `/data/logs/ujava2-service-manager.log` | 修复后持续更新 |
| cron 输出日志 | 192.168.5.70 `/var/log/ujava2-cron.log` | 修复后无 WARNING 退出、无 tee 报错 |
| 问题处理文档 | `Docs/PRD/自动化部署脚本/新统一平台/问题处理/_PRD_ujava2脚本死锁导致日志停止_问题处理.md` | 2026-09-01 创建 |
| 计划执行文档 | `Docs/PRD/自动化部署脚本/新统一平台/问题处理/_PRD_ujava2脚本死锁导致日志停止_问题处理_计划执行.md` | 2026-09-01 创建 |
| 历史同类问题 | `Docs/PRD/自动化部署脚本/新统一平台/问题处理/java监测脚本执行异常_问题处理.md` | 同一脚本早前问题(日志混乱/docker 报错/HTTP 200 误判) |
| 服务器凭据 | root / Ubains@123 @ 192.168.5.70 | Windows 本地无 sshpass,SSH 操作经 paramiko 密码认证 |
---
## 给接手者的话
> **2026-09-01 新会话(首次创建)**:新统一平台 ujava2-startup.sh flock 死锁问题已闭环:
>
> - **根因**:`start_malan_service`/`restart_host_extapi_service` 后台启动守护进程时未 `exec 200>&-` 关闭 flock 锁 fd,malan(常驻守护进程)继承 fd 200 后永不释放 → 13:26 后所有 cron 触发 `flock -n` 失败 → 主流程全部不执行 → 服务日志停止更新
> - **修复**:服务器部署脚本 3 处变更(两处 `exec 200>&-` + `LOG_FILE` 前置 + `mkdir -p`),与本地仓库脚本对齐;`bash -n` 通过
> - **释放死锁**:kill 持锁旧 malan(70515),新 malan(128794)不再持锁
> - **验证**:手动执行 EXIT_CODE=0;cron 15:51/15:54 两轮正常完整执行,锁自动释放,无 tee 报错
> - **文档**:问题处理 + 计划执行双文档产出于 `Docs/PRD/自动化部署脚本/新统一平台/问题处理/`
> - **未提交**:两份 PRD 文档 + 本 HANDOFF 均为新建文件,尚未 commit/推送(待用户确认)
> - **待对齐**:服务器与仓库脚本剩余差异(`RETRY_INTERVAL` 20/30、`stop_service` kill 逻辑)为旧版既有配置差异,非本次问题范围,建议后续部署流程统一
>
> 后续如需继续自动化部署相关工作,先 `Read` 本交接文档与本目录下的 PRD 问题处理文档;排查定时脚本日志停止优先看 cron 日志与锁文件持有者(`fuser -v`),踩坑警示 #1-#4 务必遵守。
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论