Files
dsh_shenxian/dsh-server-docs/04-调整方案/69-并发治理落地-commit常态化与服务器侧锁.md
T
admin 5ad755116e chore(docs): 文档库并入代码仓(R4 选 a)+ 索引/台账跟进
1) dsh-server-docs/ 从工作区(原 E:\...\aliyun-dsh-server\dsh-server-docs)**整体并入本仓**,
   保留目录名 ⇒ 仓库内 dsh-server-docs/... 的相对引用天然继续有效;旧目录(含其 .git)已归档到
   工作区 _中间产物_待清理/,未随本提交带入。
2) .gitattributes:新增 `dsh-server-docs/** -text` —— 原文档库是 `* -text` + autocrlf=false,
   必须保持纯 LF,否则会被本仓的 CRLF 规则翻掉。
3) 活引用里的绝对路径已全部改到新位置(docs 的 INDEX / README / scripts / skills + 用户级 skills
   + ~/.workbuddy/settings.json 的 hooks);历史档案(04-调整方案/、archive/)按「只增不改」未动。
   ⚠️ hooks 路径改动需「完全重启会话」才生效(配置是会话启动快照)。
4) 交接单/T08:新增 §16「生产整体切换执行记录」(形态 / 落地动作 / **4 个只有真上线才暴露的真 bug** /
   验收证据 / 回滚命令 / 残留项);台账 T08 行 → 已完成并归档;03-路线图 §二 登记 T08 收尾项。
5) 统一称谓:**「本机」只指跑 WorkBuddy 的开发机**,47 / 106 一律写「远程服务器」。
2026-09-15 18:47:13 +08:00

6.3 KiB
Raw Blame History

69 · 并发治理落地(T04):文档库 commit 常态化 + 服务器侧操作锁 + 权限统一

  • 日期:2026-09-12
  • 触发:用户「多 AI 会话同时执行迭代服务器项目,解决冲突」+ 当日 3 次实证事故(两通道并行改同一批文件致内容丢失;规划会话把已归档文件推回服务器制造"幽灵文件";T03 占位 2.5 小时未回填台账)
  • 结论一句话:把"多会话并行"从「靠人记得」变成「靠工具判据」 —— 文档库留下 git 路标、服务器侧加显式操作锁、两级锁进预检脚本,冲突在动手前就能被判定。
  • 状态:✅ 已完成(2026-09-12 15:10,exec-session-C 执行;单子 交接单/T04 已归档)

TL;DR|文档冲突靠 git status/mtime 还能看出来,服务器态变更看不出来(systemctl 不会告诉你 10 分钟前谁重启过)→ 必须靠显式锁。本档记录这套机制的最终形态与验证证据。


一、问题(为什么必须做)

风险面 实证 原有防护
文档冲突 同日两次「两会话并行改同一批文件」造成内容丢失;编号 37/38 各被两份档案占用 handoff-guard.sh 单级锁 + 全局锁(本档同日加)
文档无路标 文档库此前长期不提交 —— 没有 commit 就无法用 merge 发现撞车 本档:commit 常态化
服务器态无互斥 重启 dshs 引发用户掉线(档案 58/59 两次报障);改实例 env / 批量铺插件同样无人知会 本档:服务器侧操作锁
代码侧无路标 服务器 /opt/dshs 有 13 项未提交、HEAD 停在 ebe8075(档案 56)→ 两小时改造只存在于磁盘,误 checkout 即丢 本档:代码库留路标

二、改动(四项,逐条可复现)

# 动作 落地物
① 文档库 commit 常态化 f14d4e1(收口:登记档案 57–68 + 6 处记账修正)、229a762(补提交积压 13 项)→ git status --short 0 项
② 服务器侧第二把锁 /opt/dsh/state/.op-lock/(root 700,内含使用约定 README);工具 scripts/op-lock.sh {claim|release|status};handoff-guard.sh 新增**【1d】**分支
③ 权限统一 /opt/dsh/docs/交接单 755 → 700;README.md/T01/T03/T04 → 600(对照 04-调整方案 = 700)
④ 服务器代码库留路标 /opt/dshs:ebe8075 → 06e63ac(13 项逐条 add,禁 -A),status --short = 0
⑤ 对账工具降噪(本轮副作用修复) docs-sync-check.sh 的 find 增加 ! -path './交接单/.doing-*' ! -path './交接单/.exec-lock*' —— 此前只要有人持锁,对账就恒判「仅本地 ❌」(锁标记被当成内容差异);与 handoff-guard.sh【2】的过滤规则对齐

两级锁的分工(不要混用):

  • 本机 .exec-lock(粗) = 同一时刻只允许一个执行会话动「文档 / 代码 / 服务器」;
  • 本机 .doing-<单>(细) = 这个单归谁做;
  • 服务器 .op-lock/<操作名>(生产态) = 谁正在动线上(跨机可见)。
  • 顺序:先抢 .exec-lock → 再占 .op-lock;完工反序释放。

三、验证(命令 + 期望)

项 命令 结果
文档库路标 git -C dsh-server-docs status --short 空 ✅
锁脚本往返 bash scripts/op-lock.sh claim t1 → status → release t1 占位成功 → 🔴 t1 + OWNER 详情 → 释放后「无人占用 ✓」 ✅
guard 两态 bash scripts/handoff-guard.sh(无锁 / 造锁) 「✓ 无平台操作锁」/「⚠ 有会话正在动线上 + 🔴 + OWNER」并置 VERDICT=1 ✅
权限 ssh bt-server 'stat -c "%a %n" /opt/dsh/docs/交接单 /opt/dsh/docs/交接单/*.md' 700 + 四份 600 ✅
代码路标 ssh bt-server 'git -C /opt/dshs log --oneline -1; git -C /opt/dshs status --short | wc -l' 06e63ac / 0 ✅
文档审计 python scripts/docs-audit.py 退出码 0、无悬空引用 ✅
双端一致 bash scripts/docs-sync-check.sh 一致 122 / 不一致 0 / 仅本地 0 / 仅服务器 0 → ✅(含清掉锁标记造成的假 ❌)

过程中修掉一个自身 bug:guard 【1d】初版用 ls | grep -v '^README$' 取结果,空结果时 grep 返回 1 → 被判成"服务器不可达(离线)"(假阴性:明明没锁却提示离线)。已改为远端 || true + __NOLOCKDIR__ 哨兵区分「无锁 / 目录缺失 / 不可达」三态。

四、红线遵守

  • R7(禁批量写入):代码库 13 项逐条 add,未用 git add -A;未做任何 chown;未整目录覆盖。
  • R8(中断在线用户须先知会):本单零重启、零停机 —— 只做 git 提交、建目录、chmod、新增脚本。实测执行时服务器无在线实例(systemctl list-units "dsh-*.scope" 为空)。
  • 未 push:文档库与代码库均只做本机/服务器本地提交,推送仍待用户明确指令。
  • 未改平台运行代码:本单零功能代码改动(只新增运维工具脚本)。

五、回滚

  • 提交:git reset --soft HEAD~1(保留工作区);不要 --hard。
  • 权限:chmod 755 /opt/dsh/docs/交接单 && chmod 644 /opt/dsh/docs/交接单/README.md && chmod 600 /opt/dsh/docs/交接单/T0*.md。
  • 锁:rm -rf /opt/dsh/state/.op-lock + 删 scripts/op-lock.sh + 去掉 guard 的【1d】段 + 交接单/README §六 改回"提案"。

六、遗留(未做,需另行决策)

  1. 交接单目录属主未统一 —— 目录与 README/T01/T03 属主为 197108:197121,只有 T04 是 root:root。本单只授权 chmod;chown 属批量写(R7)→ 需单独确认。影响:700 对该 uid 仍是可读的,未达成"真 root-only"。
  2. 本机代码镜像未同步 —— D:\github\dsh_shenxian HEAD = 0e141a4(含 3567226)且自身有 10+ 项未提交 → 与服务器工作区双向分叉,merge --ff-only 不可能。属"两仓内容取舍"决策,留待用户决定。
  3. handoff-guard.sh 未接 CI/cron —— 目前靠"开工前手动跑",未强制。
  4. 服务器侧无操作审计 —— 本档只做互斥,不记录"谁在何时做了什么"。