From 2b6fe974608a9250615cd6fe183d45bdfc45a56a Mon Sep 17 00:00:00 2001 From: JianFeeeee Date: Mon, 21 Sep 2026 06:38:36 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE:=20=E6=88=91=E4=B8=8A=E4=B8=80?= =?UTF-8?q?=E6=9D=A1=E5=88=A4=E6=8D=AE**=E4=BC=9A=E8=AF=AF=E4=BC=A4?= =?UTF-8?q?=E5=B9=B6=E5=8F=91=E4=BC=9A=E8=AF=9D**=EF=BC=88=E6=8C=89?= =?UTF-8?q?=E5=89=8D=E7=BC=80=20glob=20=E6=95=B0=E7=9B=AE=E5=BD=95?= =?UTF-8?q?=EF=BC=89=E2=80=94=E2=80=94=20=E6=94=B9=E6=88=90=E5=8F=AA?= =?UTF-8?q?=E8=AE=A4=E6=9C=AC=E6=AC=A1=E9=82=A3=E4=B8=89=E4=B8=AA=E5=A4=B9?= =?UTF-8?q?=E5=85=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `437be52` 那条判据用 `find /tmp -name 'am-prune-selftest-*'` 做集合差。问题: **它把并发跑的另一个会话的夹具算成我的残留。** 实测撞到:06:33/06:34 有别的进程 建的 `am-prune-selftest-*` 出现又消失 ⇒ 那个 glob 口径会判成我的**假红**。 ## 改法:判据只认"这一次运行自己建的那三个" T2="$(mkdtree_fail)" _FIX_MINE="$T $B $T2" # 登记 ... rm -rf "$T" "$B" "$T2" for _p in $_FIX_MINE; do [ -e "$_p" ] && _FIX_LEFT="$_FIX_LEFT $_p"; done ck "自检夹具清干净(本次 3 个,残留:${_FIX_LEFT:- 无})" ... 按**路径还在不在**判,不按"新出现了几个目录"判 ⇒ 不受并发影响,且**能指出是哪一个**没清掉。 ★ 教训(与 `$T2` 那笔同族,但方向相反): **夹具归不到"这一次运行",判据就只能二选一 —— 认不出(假绿)或认错人(假红)。** 前一版是"认不出"(前缀不匹配 ⇒ 变异测不出来),这一版差点是"认错人"。 ## 三档都实跑 变异(去掉 $T2) ⇒ rc=1 22 通过/1 失败,**点名** /tmp/am-prune-selftest-e0kKQs ✓ 基线 ⇒ rc=0 23 通过/0 失败,残留: 无 ✓ 对照(预置别人的夹具) ⇒ rc=0 通过,且**别人的目录原样保留**(不误伤、不代删)✓ --- deploy/prune-deploy-artifacts.sh | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/deploy/prune-deploy-artifacts.sh b/deploy/prune-deploy-artifacts.sh index 7b3652c..1338da2 100755 --- a/deploy/prune-deploy-artifacts.sh +++ b/deploy/prune-deploy-artifacts.sh @@ -238,11 +238,6 @@ if [ "${1:-}" = "--self-check" ]; then } SIG_BEFORE="$(_tree_sig "$ROOT")" - # 自检**之前**已存在的夹具目录(正常情况下是空的,但并发跑或上次崩溃会留下)。 - # 后面按**集合差**判"本次是否清干净"—— 比对"有没有新的", - # 而不是"有没有"或"最近 10 分钟内的":前者会被上一次的残留误伤,后者依赖时钟。 - _FIX_BEFORE="$(find "${TMPDIR:-/tmp}" -maxdepth 1 -name 'am-prune-selftest-*' 2>/dev/null | sort)" - T="$(mktree)" out="$(run "$T")"; rc=$? # 干跑:看报告 ck "干净样本:干跑成功(退出码 $rc)" "$([ "$rc" = 0 ] && echo 1 || echo 0)" @@ -289,7 +284,13 @@ if [ "${1:-}" = "--self-check" ]; then # 这个时间戳 ⇒ shim 会把夹具自己的清理一起打掉,红的全是【干净样本】。 # 实测:基线 22 通过/0 失败;两种 shim 都退化成 16 通过/6 失败(合计恒 22, # 详见 `del()` 里的注释 —— 那里也记了这三个数**第一版为什么是错的**)。 + # ★ 判"本次夹具清干净"必须**只认这一次运行自己建的三个**(`$T`/`$B`/`$T2`), + # 不能用 `find /tmp -name 'am-prune-selftest-*'` 去数整个前缀 —— + # 那样会把**并发跑的另一个会话的夹具**算成我的残留(2026-09-21 实测撞到: + # 06:33/06:34 有别的进程建的目录出现又消失,glob 口径会判成我的假红)。 + # **夹具归不到"这一次运行",判据就只能二选一:认不出(假绿)或认错人(假红)。** T2="$(mkdtree_fail)" + _FIX_MINE="$T $B $T2" cat > "$T2/fake-rm" <<'FAKERM' #!/usr/bin/env bash case "$*" in *20260101-000000*) echo "fake rm: 模拟删除失败" >&2; exit 1;; esac @@ -318,15 +319,14 @@ FAKERM # **一个自检脚本自己不干净,比它测出来的红更值得先修。** # 判据:跑完 `--self-check` 后按前缀数目录,必须**一个都不剩**(见下面的自检后置)。 rm -rf "$T" "$B" "$T2" - # 后置:按**集合差**确证本次的夹具真被清掉(不是"我以为清了")。 - # 只关心"本次新出现的",所以上次的残留不会把它打成假红; - # 这条判据正好能抓住"新夹具忘了加进清理列表"—— 那正是 `$T2` 的病史。 - _FIX_AFTER="$(find "${TMPDIR:-/tmp}" -maxdepth 1 -name 'am-prune-selftest-*' 2>/dev/null | sort)" - _FIX_LEFT="$(comm -13 <(printf '%s\n' "$_FIX_BEFORE") <(printf '%s\n' "$_FIX_AFTER") | grep -c . || true)" - ck "自检夹具清干净(本次新建的残留 = $_FIX_LEFT 个,须为 0)" "$([ "$_FIX_LEFT" = 0 ] && echo 1 || echo 0)" - if [ "$_FIX_LEFT" != 0 ]; then - printf '%s\n' "$_FIX_AFTER" | comm -13 <(printf '%s\n' "$_FIX_BEFORE") - | sed 's/^/ 残留: /' >&2 - fi + # 后置:确证**本次这三个**夹具真被清掉(按路径逐个判,不按前缀数目录)。 + # 用"路径还在不在"而不是"新出现了几个目录": + # 前者不受并发会话影响,且能直接指出是哪一个没清掉。 + _FIX_LEFT="" + for _p in $_FIX_MINE; do + [ -e "$_p" ] && _FIX_LEFT="$_FIX_LEFT $_p" + done + ck "自检夹具清干净(本次 3 个,残留:${_FIX_LEFT:- 无})" "$([ -z "$_FIX_LEFT" ] && echo 1 || echo 0)" echo if [ "$fails" != 0 ]; then echo " 判据自检失败 $fails/$total 项 —— 清理器本身不可信,不要用它删东西" >&2