tools-sync: 传输故障时登录 gitea 自愈,并让"同步成功"包含"别人拉得到"
授权本 skill 在同步传输出问题时登录 gitea 服务器诊断并修复。连接参数走 skills_env.md 的 GITEA_* 段(模板同步给出占位符与填写要点),不写死在脚本里。 新增 scripts/gitea_doctor.ps1(Windows 侧驱动): - 分两个面探测传输——refs 面(ls-remote) 与 pack 面(--filter=tree:0 的极小 clone)。 两面独立坏,区别就是整个诊断:2026-08 那次只有 pack 面死了,push 和 ls-remote 全程正常,故障因此藏了 8 天。两面都好就直接返回,不连服务器。 - 坏了才 ssh,tailscale 直连优先、frps 跳板兜底。 - 修完不采信服务端自述,回到客户端重新探一次 pack 面才算数。 新增 scripts/gitea_triage.sh(服务端执行):8 项检查各打 PASS/FAIL,--fix 只做 可逆修复(隔离被污染的 gitconfig 并重启让 gitea 重建、按 git 模板还原被篡改的 hook、删 /tmp 载荷、还原被包了一层的 git、拉起停掉的容器),破坏性操作另需 --allow-destructive。检查表把这次的两个坑固化下来:packgen 必须带 --stateless-rpc (clone file:// 走的不是 HTTP 那条码路,假阴性把上一轮排查带偏成"gitea 版本 bug"), 以及全局 gitconfig 在 /data/gitea/home 而不是 /data/git。 sync_repos.ps1: - pull/push 报传输类错误时自动调医生并重试一次(-NoDoctor 可关)。 - 收尾增加 fetchability 探针。push 成功不等于同步成功——服务端发不出 pack 时, 刚推上去的东西别的机器照样拉不到,这轮就该判失败。ls-remote 闸门只验 ref 面, 测试中确实出现过"同步报成功而服务器仍是故障态"。 脚本用 scp 送到服务端执行而不是管道进 sh -s:PS 5.1 会给管道内容加 UTF-8 BOM, 糊在 shebang 上,sh 报的错会指向解释器而不是真原因。 验证:注入真实故障(packObjectsHook 指向 /bin/true,同样产出空 pack)后整链跑通 5 次——检出→隔离→重启→重建→客户端复验,包括从同步主流程自动触发的那次。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015tMFjKGgxdmxJ28dyXdx1u
This commit is contained in:
+62
-18
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
name: tools-sync
|
name: tools-sync
|
||||||
description: 在本机统一同步并配置 Claude Code 与 Codex 的 skills、MCP server 和开发环境:将 ~\.claude\skills 和 ~\.codex\skills 与 git.rpchannel.com 上的 bowei/skills-win 仓库保持同步,审计 skills 中的硬编码参数并迁移到本机 ~\skills_env.md,校验 langgraph conda 环境,双向发现并补齐 Claude Code 与 Codex 的用户 MCP 注册,同时确保 E:\MCP_design 下所有 MCP 均已注册。当用户提到"同步skills"、"skills同步"、"tools sync"、"tools-sync"、"同步codex"、"同步MCP"、"环境同步"、"skills-win"、"把skills推上去/拉下来"、"新电脑配置claude/codex环境"、"检查MCP注册"、"skills_env"时,必须使用此技能,即使用户没有明确说"skill"二字。
|
description: 在本机统一同步并配置 Claude Code 与 Codex 的 skills、MCP server 和开发环境:将 ~\.claude\skills 和 ~\.codex\skills 与 git.rpchannel.com 上的 bowei/skills-win 仓库保持同步,审计 skills 中的硬编码参数并迁移到本机 ~\skills_env.md,校验 langgraph conda 环境,双向发现并补齐 Claude Code 与 Codex 的用户 MCP 注册,同时确保 E:\MCP_design 下所有 MCP 均已注册。同步的传输一旦出问题,本 skill 还负责登录 gitea 服务器(上海 mac 的 Docker 容器)诊断并修复,直到同步真正成功。当用户提到"同步skills"、"skills同步"、"tools sync"、"tools-sync"、"同步codex"、"同步MCP"、"环境同步"、"skills-win"、"把skills推上去/拉下来"、"新电脑配置claude/codex环境"、"检查MCP注册"、"skills_env",或者 git.rpchannel.com 出现"clone/fetch 失败"、"bad pack header"、"early EOF"、"RPC failed"、"推不上去/拉不下来"、"gitea 坏了/连不上/要修"时,必须使用此技能,即使用户没有明确说"skill"二字。
|
||||||
---
|
---
|
||||||
|
|
||||||
# tools-sync:Claude Code / Codex 工具链同步
|
# tools-sync:Claude Code / Codex 工具链同步
|
||||||
@@ -70,23 +70,10 @@ powershell -File <skill目录>\scripts\sync_repos.ps1 -RepoUrl <origin_url>
|
|||||||
写入,所以是可证同一份历史,不是近似复制。重建后
|
写入,所以是可证同一份历史,不是近似复制。重建后
|
||||||
`git update-ref refs/remotes/origin/main <sha>` + `git rebase <sha>`,本地历史就归位了,
|
`git update-ref refs/remotes/origin/main <sha>` + `git rebase <sha>`,本地历史就归位了,
|
||||||
服务恢复后一条 `git push` 即可。**任何情况下都不要 force push**(会丢掉别的机器的 commit)。
|
服务恢复后一条 `git push` 即可。**任何情况下都不要 force push**(会丢掉别的机器的 commit)。
|
||||||
- **clone/fetch 报 `bad pack header` / `early EOF`,但 `git ls-remote` 和 Gitea 网页/API 正常**:
|
- **clone/fetch 报 `bad pack header` / `early EOF` / `RPC failed`,而 `ls-remote` 和网页正常**:
|
||||||
服务端把 pack 生成外包给了一个不产出内容的程序。**2026-09-02 实际发生过一次**,
|
服务端传输故障,**脚本会自动调用阶段 1.5 的医生修复并重试**,通常你什么都不用做。
|
||||||
症状是 `POST /git-upload-pack` 记 200 OK、耗时也正常,响应体却只有 `0008NAK`。
|
自动修复没搞定时按阶段 1.5 的手工梯子往下走。绝不要因为"服务端坏了"就把这轮
|
||||||
别去猜版本或网络,按这个阶梯两三步就能定位(每一步都排掉一层):
|
记成已同步。
|
||||||
1. 容器/宿主机内直连 gitea 端口 clone —— 还失败就与 frp、反向代理无关;
|
|
||||||
2. `git upload-pack --stateless-rpc <repo裸路径> < 一个手写的 want/done 请求 | wc -c`
|
|
||||||
—— 出得来几 MB 就说明 git 本身没病,**注意必须带 `--stateless-rpc`**,
|
|
||||||
用 `clone file://` 走的不是 HTTP 那条码路,测了不算数;
|
|
||||||
3. 在 gitea 和 git 之间插一个 wrapper(把 `/usr/bin/git` 换成脚本,`tee` 下 argv/env/
|
|
||||||
stdin/stdout)跑一次 clone。**上次就是这一步定的案:upload-pack 只吐了 17 字节、
|
|
||||||
stderr 全空**——不是 gitea 丢包,是 git 自己被指使着不干活。
|
|
||||||
根因在 gitea 的全局 gitconfig(`$HOME/.gitconfig`,docker 下 HOME=`/data/gitea/home`,
|
|
||||||
**不是** `/data/git`)里被注入了 `[uploadpack] packObjectsHook`。该配置会把
|
|
||||||
`git pack-objects` 整个替换掉,指向的脚本不产出 pack 就得到空包。
|
|
||||||
处置:备份该文件取证 → 移走 → 重启 gitea(它启动时会重建一份干净的)→
|
|
||||||
在容器内和公网各 clone 一次验证。同时检查 hook 脚本有没有被追加执行语句、
|
|
||||||
`/tmp` 有没有配套载荷——这是一条完整的 RCE 链,不是配置写错。
|
|
||||||
- **push 被拒(认证)**:检查凭据管理器条目;新机器上用
|
- **push 被拒(认证)**:检查凭据管理器条目;新机器上用
|
||||||
`git config --global credential.helper manager` 后重试一次,让 credential
|
`git config --global credential.helper manager` 后重试一次,让 credential
|
||||||
helper 弹窗或从 skills_env.md 读凭据拼一次性 URL 完成首次认证。
|
helper 弹窗或从 skills_env.md 读凭据拼一次性 URL 完成首次认证。
|
||||||
@@ -94,6 +81,62 @@ powershell -File <skill目录>\scripts\sync_repos.ps1 -RepoUrl <origin_url>
|
|||||||
- **不该入库的文件**:commit 前扫一眼 `git status`,运行时产物(.sqlite、.pckl、
|
- **不该入库的文件**:commit 前扫一眼 `git status`,运行时产物(.sqlite、.pckl、
|
||||||
日志、缓存目录)应加进 `.gitignore` 而不是提交。看到就顺手补 `.gitignore`。
|
日志、缓存目录)应加进 `.gitignore` 而不是提交。看到就顺手补 `.gitignore`。
|
||||||
|
|
||||||
|
## 阶段 1.5 — 服务端诊断与修复(gitea 坏了就上去修)
|
||||||
|
|
||||||
|
同步的前提是传输是通的。**本 skill 有权登录 gitea 服务器并做修复**,连接参数取自
|
||||||
|
`skills_env.md` 的 `GITEA_*` 段(阶段 0 已读;缺就先补,模板里有占位符和填写要点)。
|
||||||
|
|
||||||
|
`sync_repos.ps1` 已经把这件事接进主流程,正常情况下**你不需要手动做任何事**:
|
||||||
|
|
||||||
|
- `pull` / `push` 报传输类错误(`bad pack header`、`early EOF`、`RPC failed`、
|
||||||
|
`remote end hung up`…)→ 自动调 `gitea_doctor.ps1 -Fix` → 修好后重试一次;
|
||||||
|
- 每轮同步收尾还有一次 **fetchability 探针**:push 成功不等于同步成功,
|
||||||
|
服务端发不出 pack 时别的机器照样拉不到。探针不通就判本轮失败。
|
||||||
|
- `-NoDoctor` 关掉这套自动行为,`-AllowDestructive` 放开破坏性修复(见下)。
|
||||||
|
|
||||||
|
单独跑:
|
||||||
|
|
||||||
|
```powershell
|
||||||
|
powershell -File <skill目录>\scripts\gitea_doctor.ps1 # 只检查并报告
|
||||||
|
powershell -File <skill目录>\scripts\gitea_doctor.ps1 -Fix # 检查→登录修复→复验
|
||||||
|
```
|
||||||
|
|
||||||
|
医生先在本机分两个面探测——**refs 面**(`ls-remote`)和 **pack 面**(一次
|
||||||
|
`--filter=tree:0 --depth 1` 的极小 clone)。两个面独立坏,区别就是整个诊断:
|
||||||
|
2026-08 那次只有 pack 面死了,push 和 `ls-remote` 全程正常,所以故障藏了 8 天。
|
||||||
|
两面都好就直接返回,不会去连服务器。
|
||||||
|
|
||||||
|
坏了才 ssh 上去跑 `gitea_triage.sh`(scp 过去执行,不走 stdin 管道——PS 5.1 会给
|
||||||
|
管道内容加 UTF-8 BOM,糊在 shebang 上,报出来的错会指向解释器而不是真原因)。
|
||||||
|
服务端按这个梯子逐层排查,每项打 `PASS/FAIL`:
|
||||||
|
|
||||||
|
| 检查 | 看什么 | `--fix` 时怎么修 |
|
||||||
|
|---|---|---|
|
||||||
|
| container | 容器在不在、起没起 | `docker start` |
|
||||||
|
| disk | `/data` 剩余空间 | 只报告 |
|
||||||
|
| **gitconfig** | 全局 gitconfig 有没有 `packObjectsHook` / `core.hooksPath` / `sshCommand`,文件是不是被撑大 | 隔离该文件 + 重启容器,gitea 自己重建干净的 |
|
||||||
|
| hooks | 仓库 hook 里有没有引用 `/tmp` 的执行语句 | 用 git 模板还原 |
|
||||||
|
| payload | `/tmp` 下有没有配套载荷 | 删除 |
|
||||||
|
| gitbin | `/usr/bin/git` 是不是被包了一层(`git.real` 存在即是) | 还原真 git |
|
||||||
|
| **packgen** | `git upload-pack --stateless-rpc` 能否产出 pack | 只报告(它说明 git 被指使着不干活) |
|
||||||
|
| httpclone | 容器内直连 3000 端口能否 clone | 只报告 |
|
||||||
|
|
||||||
|
两条排查纪律,都是 2026-09-02 用一周代价换来的:
|
||||||
|
|
||||||
|
- **`packgen` 必须带 `--stateless-rpc`**。`clone file://` 走的不是 HTTP 那条码路,
|
||||||
|
测通了不能说明任何问题——上一轮排查就是被这个假阴性带偏,误判成 gitea 版本 bug。
|
||||||
|
- **`gitconfig` 在 `/data/gitea/home/.gitconfig`,不是 `/data/git/.gitconfig`**。
|
||||||
|
查错路径会得到"文件不存在",从而排除掉真凶。
|
||||||
|
|
||||||
|
医生只做**可逆**修复;`-AllowDestructive` 才放开可能丢数据的操作(重建容器、仓库手术),
|
||||||
|
默认路径一个都不需要。修完不信服务端的自述,回到客户端重新探一次 pack 面才算数。
|
||||||
|
|
||||||
|
**梯子走完仍未修好**,说明是这套已知故障之外的新东西。此时再上手工三步(每步排掉一层):
|
||||||
|
容器内直连 3000 端口 clone → `upload-pack --stateless-rpc` 手喂 want/done 数字节 →
|
||||||
|
把 `/usr/bin/git` 换成 `tee` 掉 argv/env/stdin/stdout 的 wrapper 跑一次 clone。
|
||||||
|
第三步能直接看出是 gitea 丢了 pack 还是 git 自己没产出——上次就是这一步定的案。
|
||||||
|
定位到新根因后,把它补进 `gitea_triage.sh` 的检查表,别只修这一次。
|
||||||
|
|
||||||
## 阶段 2 — 对齐 ~\.codex\skills(junction 对账)
|
## 阶段 2 — 对齐 ~\.codex\skills(junction 对账)
|
||||||
|
|
||||||
同一个脚本接着处理 codex 侧。它对主副本的每个顶层 skill 目录做三件事:
|
同一个脚本接着处理 codex 侧。它对主副本的每个顶层 skill 目录做三件事:
|
||||||
@@ -262,6 +305,7 @@ setupAgenticToolkit("configure", Agents=["claude-code","codex"], ...
|
|||||||
## skills 同步
|
## skills 同步
|
||||||
- ~\.claude\skills: <pull/push 结果,commit 摘要>
|
- ~\.claude\skills: <pull/push 结果,commit 摘要>
|
||||||
- 远端校验: origin/main = <sha>,与本地一致 / **不一致:N 个 commit 滞留本机**
|
- 远端校验: origin/main = <sha>,与本地一致 / **不一致:N 个 commit 滞留本机**
|
||||||
|
- 服务端: 传输两面均正常 / 医生修复了 <哪几项> / **仍不可用:<RESULT 行>**
|
||||||
- ~\.codex\skills: <pull 结果,注册差集>
|
- ~\.codex\skills: <pull 结果,注册差集>
|
||||||
## 硬编码审计
|
## 硬编码审计
|
||||||
- 本次修复: <清单>
|
- 本次修复: <清单>
|
||||||
|
|||||||
Reference in New Issue
Block a user