diff --git a/deploy/prune-deploy-artifacts.sh b/deploy/prune-deploy-artifacts.sh index 23cd443..936665f 100755 --- a/deploy/prune-deploy-artifacts.sh +++ b/deploy/prune-deploy-artifacts.sh @@ -93,8 +93,25 @@ del() { # **只在成功后才累加**,收尾汇总不再虚报。 if [ "$APPLY" = "1" ]; then # `$RM` 只是为了**让自检能喂一个"删不动"的失败**(见 --self-check 那一段): - # 默认就是 `rm`,生产行为逐字不变。不用 PATH shim 是因为 `in_use` 会把 - # 命令行里含该路径的进程判成"在用",而自检必须把路径写在命令行上。 + # 默认就是 `rm`,生产行为逐字不变。 + # + # ★ 为什么**不**用 PATH shim(pi 2026-09-14 建议过,我实测后否掉,2026-09-21 补正) + # + # 我原先在这里写的原因是"`in_use` 会把命令行里含该路径的进程判成在用" —— + # **那是我没量过的推断,而且量下来是错的**:自检跑完 `正在被使用` 出现 **0** 次, + # `in_use` 根本没触发。真正的失败原因是**夹具与该路径撞了同一个时间戳**: + # + # 自检夹具建的就是 `$T/agentmail-gateway.bak-20260101-000000`(`mktree`), + # 而「窗口外那一个」恰恰也是它 —— 于是任何"对 `20260101-000000` 失败"的 shim + # 会连**夹具自己的清理**一起打掉。实测(两种 shim 都试过): + # 基线 ⇒ 通过 22 / 失败 1 + # shim(全 rm) ⇒ 通过 16 / 失败 9 + # shim(只该目标)⇒ 通过 16 / 失败 9 ← 与全量 shim **一样**,因为目标就是夹具 + # 红的六条还都是【干净样本】("窗口外没了、窗口内还在"等)—— 即 shim 把 + # **本应绿的样本**打红,测到的是"夹具坏了"而不是"删除失败被报出来了"。 + # + # ⇒ 让 `rm` 失败这件事,只有**注入点**能精确限定在"del() 这一次调用"上; + # PATH shim 的作用域是**整个进程**,而自检夹具活在同一个进程里,躲不开。 if ! "$RM" -rf "$path"; then printf ' [FAIL] 删不掉:%s(权限/只读挂载/immutable?)\n' "$path" >&2 @@ -244,8 +261,10 @@ if [ "${1:-}" = "--self-check" ]; then # 早先我以为覆盖不了它:本机以 root 跑,权限拦不住 `rm`;`unshare -r` 被拒 # (`/proc/self/uid_map: Permission denied`);tmpfs 无 `chattr +i`。 # pi 指出第三条路是**让 rm 自己失败**,而不是去改机器的权限 —— 于是有了 `$RM` 覆盖点。 - # (不用 PATH shim:`in_use` 会把命令行里含该路径的进程判成"在用", - # 而自检必须把路径写在命令行上。) + # ★ 但"让 rm 失败"必须走**注入点**,不能走 PATH shim:shim 的作用域是整个进程, + # 而下面这些夹具(`mktree`)活在同一个进程里、且用的**就是** `20260101-000000` + # 这个时间戳 ⇒ shim 会把夹具自己的清理一起打掉,红的全是【干净样本】。 + # 实测:基线 22 通过/1 失败;两种 shim 都退化成 16 通过/9 失败(详见 `del()` 里的注释)。 T2="$(mkdtree_fail)" cat > "$T2/fake-rm" <<'FAKERM' #!/usr/bin/env bash