CI runner 修日志噪声与 -Status 假警:PS5.1 把原生 stderr 包成 ErrorRecord

双看门狗缺陷已实测收敛:管理员 -StartNow 清掉 3 个残留(孤儿看门狗 26900/19716 +
占锁 daemon 53848)→ "daemon up: pid 40360 (single instance)",监管链恢复为
svchost(任务) → 看门狗 → daemon,看门狗日志 25 秒零增长,runner 回 online。
切换瞬间新看门狗先失败 1~2 次(旧 daemon 刚死、锁未释放)后自愈,属预期。

顺带查出并修掉两个由验证动作暴露的问题:

1) 日志噪声:daemon 把日志写到 stderr,PS 5.1 的 2>&1 会把每行原生 stderr 包成
   ErrorRecord,Out-File 渲染出 "gitea-runner.exe : " 前缀 + 4 行 CategoryInfo 块。
   实测对比(用无效子命令产生真实 stderr):& exe 2>&1 | Out-File 把 2 行真日志写成
   8 行——每 4 行有 3 行是 PowerShell 噪声,而且就在文档让大家第一个打开的文件里。
   改为 2>&1 | ForEach-Object { "$_" } | Out-File -Encoding utf8:实测与 cmd 包装等价
   但不用操心 cmd 对含空格路径的引号剥离,ErrorRecord.ToString() 即原始行,
   $LASTEXITCODE 不受影响(看门狗靠它打印退出码)。§7.2 方式 B 的示例原本正是
   "> log 2>&1"(UTF-16LE + ErrorRecord 双坑),已改;新增 §7.3 汇总这两条陷阱。

2) -Status 两处不诚实:① 非管理员读不到 SYSTEM 进程的 CommandLine(返回 null),
   过滤器静默匹配 0 个 → 会谎报"没有看门狗"(今天两次被这个假象误导),改为明说
   "需提权";② 重启循环判据原本靠"日志尾部 40 行里有没有 lock 字样",而日志不轮转,
   修好之后旧失败仍留在尾部 → 对健康 runner 报假警。改看 daemon 进程存活时长
   (活过 10 秒重拉间隔就不可能在循环里);用 CIM CreationDate,因为
   Process.StartTime 对 SYSTEM 进程不可读。

验证:bootstrap parse 0 错 / 纯 ASCII / -Status 与 -DryRun 均正常;
check_doc_links.py --all 125 篇 0 问题;pre-commit run --all-files 17 项全 Passed。

注:磁盘上的 run_runner_watchdog.ps1 仍是旧模板,噪声修复要下次管理员 -StartNow
(或开机自启)时才生效,纯观感问题,不必专门再重启一次 runner。
This commit is contained in:
2026-10-12 17:59:45 +08:00
parent 49f3e2dac5
commit 3557b60ceb
3 changed files with 84 additions and 15 deletions
+3
View File
@@ -66,6 +66,8 @@
> 于是新看门狗每 10 秒失败一次(`runner file is already locked by another process`)——
> **而 runner 在网页上照样显示 online**,CI 看着正常,任务其实谁也没管。
> 现在 `-StartNow` 会先清掉这些残留进程再启动(约离线几秒),`-Status` 也会报出重复实例。
> **2026-10-12 已实测收敛**:清掉 3 个残留后 `daemon up: pid … (single instance)`,
> 监管链 `svchost(任务) → 看门狗 → daemon` 恢复,runner 回 online。
## 相关文档
@@ -79,6 +81,7 @@
| 日期 | 变更 |
|---|---|
| 2026-10-12 | ✅ 双看门狗缺陷**实测收敛**(管理员 `-StartNow` 清掉 3 个残留 → 单实例、链路恢复、runner online)。另修两处:daemon 日志走 stderr 被 PS 5.1 `2>&1` 包成 ErrorRecord(2 行真日志写成 8 行,每 4 行 3 行噪声)→ 启动器改 `ForEach-Object { "$_" }`;`-Status` 诚实化(非管理员读不到 SYSTEM 进程命令行 → 明说需提权而非谎报"无看门狗";重启循环判据改看进程存活时长,不再靠不轮转日志的尾部字符串报假警)。详见指南 §7.3 |
| 2026-10-12 | 🔴 **修复"双看门狗抢 `.runner.lock`"缺陷**:`Unregister-ScheduledTask` 不停旧实例进程 → 孤儿看门狗养着旧 daemon 占锁,新看门狗每 10 秒失败一次,而 runner 网页照样 online、`-Status` 也说"在跑"。现 `-StartNow` 先清残留进程再启动、`-Status` 报重复实例与锁冲突。同日清理机器侧:`config.yaml` 头部错误指引("改用 sc.exe / New-Service")改为看门狗口径,删除已废弃的 `deploy_runner_task.ps1` 与 `run_runner.cmd`,`check_env.ps1` 提示同步改指 bootstrap |
| 2026-10-12 | **单一口径清理**:合并稿初版对 4 处分歧"两说并存",现统一为本机实测现状——注册口径(`gitea-runner v4.0.1` / `D:\Docker\act_runner` / `127.0.0.1:3001`,旧 `act_runner v0.2.11` + `C:\act_runner` 段删去可复制命令只留警示)、`config.yaml`(`fetch_timeout: 1m0s`、`timeout: 30m0s`)、常驻方式(只认看门狗,`deploy_runner_task.ps1` 标废弃)、验收数字(L0.5 `288/288`,历史数字标注为快照)。并补"机器侧遗留脚本勿误用"警示 |
| 2026-10-12 | **新建本目录**:远程 CI 内容原先散在 `docs/环境与部署/`(两篇互相重叠的指南)、`docs/测试说明/测试开发标准流程.md` §9、`AGENTS.md` 提交门禁节共 4 处,约 2000 行;现合并为单一指南并把 `AGENTS.md` 压成一行指针。动因:远程 CI 只涉及本机一台 runner,与日常开发规范混在一起每次会话都被读,造成困惑 |