補上 stat -f 診斷的最後一層:連離開碼都不可靠(inkstone/ISEP#90 ④)
總管自己驗這一格量到 exit=0,我量到 exit=1。**兩個都是真的**,
而分歧本身就是最後一塊拼圖:
**GNU 的 `-f` 是 `--file-system`,布林旗標、不接格式字串**
⇒ `%m` 不是格式,它被當成**另一個檔名運算元**
⇒ 離開碼取決於「cwd 裡有沒有一個叫 `%m` 的檔」:
A. 沒有(一般情況) → exit 1 ⇒ `||` 會跑 ⇒ 正確的秒數接在垃圾後面
B. 剛好有 → exit 0 ⇒ `||` 不會跑 ⇒ 整包連一個數字都沒有
兩種情況閘的結果一樣:MT 都不是純數字、戳記都作廢。(實測 GNU coreutils 9.4,兩種都重現過)
🔴 教訓比原本寫的更尖銳:舊寫法的 `||` fallback 救不了,
**不是因為它沒跑,而是因為「跑不跑」根本不由這支腳本決定**——
它由「cwd 裡有沒有某個檔名」決定。
一個行為取決於 cwd 有沒有某個檔的判斷式,不管跑不跑都是壞的。
⇒ 所以修法不能只是「把順序反過來」,**每一步都要驗它是不是純數字**
(lib/mtime.sh 本來就是這樣寫的,現在把理由寫進去了)。
gate-ok 測試補第 ⑰ 條守這一層:cwd 裡有一個叫 `%m` 的檔時,file_mtime 仍要回純數字。
16 → 17 條,TESTING.md 的 A16 一併更新。
This commit is contained in:
+7
-3
@@ -131,11 +131,11 @@ bash hooks/tests/prod-write-guard.test.sh hooks/prod-write-guard.sh
|
||||
- 「卡點二」2 條任一紅 ⇒ 「談論它」又被當成「執行它」(同款第八次),
|
||||
或是剝了內文之後連真的部署都放行了
|
||||
|
||||
### A16 — 「總管可以放行」那道門真的打得開:16 條
|
||||
### A16 — 「總管可以放行」那道門真的打得開:17 條
|
||||
```
|
||||
bash hooks/tests/gate-ok.test.sh
|
||||
```
|
||||
**該看到**:`通過 16 條,失敗 0 條`。
|
||||
**該看到**:`通過 17 條,失敗 0 條`。
|
||||
|
||||
**它在守什麼**(inkstone/ISEP#90 ④,2026-08-28 實查):三支閘
|
||||
(`prod-write-guard`/`main-and-prod-push-guard`/`stage-before-prod-guard`)
|
||||
@@ -151,6 +151,10 @@ bash hooks/tests/gate-ok.test.sh
|
||||
08-11、08-12 兩次真的被穿透之後才補上的,不准為了「好放行」而鬆掉
|
||||
- ⑫ 紅 ⇒ `gate-ok` 在解不出 repo 時留下了一枚註定打不開的空戳記,
|
||||
那會讓人以為門開了(而空戳記本身就是 08-12 那把萬用鑰匙的形狀)
|
||||
- ⑰ 紅 ⇒ 判準又變回「行為取決於 cwd 裡有沒有一個叫 `%m` 的檔」。
|
||||
這條是這個 bug 的最後一層:**GNU 的 `-f` 是布林旗標,`%m` 被當成另一個檔名運算元**
|
||||
⇒ 有那個檔就 `exit 0`、`||` 連跑都不跑。所以修法不能只是「把順序反過來」,
|
||||
**每一步都要驗它是不是純數字**
|
||||
|
||||
⚠️ 這支會真的寫 `/tmp` 的戳記檔(那是閘寫死的路徑)。**不要在「已經蓋好戳記正要推東西」
|
||||
的當下跑它**——它會把那枚戳記洗掉。
|
||||
@@ -389,7 +393,7 @@ B2(信標那行)/B3(setup 輸出)/B4(閘的訊息)三個畫面
|
||||
| **A10 人閘警察準度** | 總管 | ✅ 9/9,連跑三次(2026-08-26),A 群誤攔 0 |
|
||||
| **A11 派工單只剩票號** | 總管 | ✅ 19/19(2026-08-27) |
|
||||
| **A12 留言身份欄(兩道門)** | 總管 | ✅ 11/11(2026-08-27) |
|
||||
| **A16 放行的門真的打得開** | 總管 | ✅ 16/16(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A16 放行的門真的打得開** | 總管 | ✅ 17/17(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A17 未推警察不誤攔雲端分支** | 總管 | ✅ 10/10(2026-08-28,inkstone/ISEP#90) |
|
||||
| **A18 信標會報雲端接線缺陷** | 總管 | ✅ 14/14(2026-08-28,inkstone/ISEP#90) |
|
||||
| A7 plugin 裝得起來 | 總管 | ✅ |
|
||||
|
||||
@@ -102,6 +102,53 @@ stat: cannot read file system information for '%m': No such file or directory
|
||||
⇒ `case "$NOW$MT" in *[!0-9]*) return 1` 必然命中
|
||||
⇒ **在 Linux(=每一個雲端 session)上,那三支閘的戳記永遠不會被接受。**
|
||||
|
||||
### 再往下一層:`-f` 根本不吃格式參數,所以連離開碼都不可靠
|
||||
|
||||
總管 2026-08-28 自己驗這一格時量到 `exit=0`,而我量到 `exit=1`。
|
||||
**兩個都是真的**,而分歧本身就是這個 bug 最後一塊拼圖:
|
||||
|
||||
**GNU 的 `-f` 是 `--file-system`,它是布林旗標、不接格式字串**
|
||||
⇒ `%m` 不是格式,它被當成**另一個檔名運算元** ⇒ 離開碼取決於
|
||||
「當前目錄裡有沒有一個叫 `%m` 的檔」:
|
||||
|
||||
```
|
||||
$ cd /tmp/statprobe && touch .mt
|
||||
|
||||
# A. 沒有名為 %m 的檔(一般情況)
|
||||
$ stat -f %m .mt ; echo "exit=$?"
|
||||
stat: cannot read file system information for '%m': No such file or directory
|
||||
File: ".mt" … ← 檔案系統資訊照樣印到 stdout
|
||||
exit=1 ← `||` **會**跑 ⇒ 正確的秒數接在那堆垃圾後面
|
||||
|
||||
# B. 剛好有一個叫 %m 的檔
|
||||
$ touch '%m' && stat -f %m .mt ; echo "exit=$?"
|
||||
exit=0 ← `||` **不會**跑 ⇒ 整包連一個數字都沒有
|
||||
```
|
||||
|
||||
(實測環境:`stat (GNU coreutils) 9.4`)
|
||||
|
||||
**兩種情況下閘的結果一模一樣**——`MT` 都不是純數字,
|
||||
`case "$NOW$MT" in *[!0-9]*) return 1` 都必然命中,戳記都作廢:
|
||||
|
||||
```
|
||||
情況 A:非數字 ⇒ return 1 ⇒ 戳記作廢
|
||||
情況 B:非數字 ⇒ return 1 ⇒ 戳記作廢
|
||||
```
|
||||
|
||||
🔴 **這一層才是真正該記住的教訓**:舊寫法的 `||` fallback 之所以救不了,
|
||||
**不是因為它沒跑,而是因為「跑不跑」根本不由這支腳本決定**
|
||||
——它由「當前目錄裡有沒有一個叫 `%m` 的檔」決定。
|
||||
一個**行為取決於 cwd 裡有沒有某個檔名**的判斷式,不管跑不跑都是壞的。
|
||||
|
||||
⇒ 所以 `lib/mtime.sh` 的修法不是「把順序反過來」而已,是
|
||||
**每一步都驗它是不是純數字**:這個 bug 的成因正是「命令失敗了卻還是印了東西」,
|
||||
**只看離開碼會再被騙一次**。
|
||||
|
||||
📌 這一格的實害(總管 2026-08-28 原話):「我今天為了發一則通知,
|
||||
用了兩種方式蓋 `prod-write-ok` 都無效,一度以為是權限問題。」
|
||||
⇒ **閘不會告訴你門是壞的**,所以人會往錯的方向查(權限、classifier、設定),
|
||||
而根因在閘自己身上。
|
||||
|
||||
🔴 **後果**:那三支閘在雲端**等於純擋**。總管照著閘自己印的指示做,
|
||||
做幾次都打不開,**而閘不會告訴他門是壞的**。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user