編按:本文綜合整理自 GitHub Issue #28224、Notebookcheck 報導 與 Hacker News 討論串,並加入 Siami 編輯部觀點與分析。
事件概要
OpenAI 的 Codex CLI 工具被回報存在嚴重日誌寫入 Bug——一個本該只是儲存診斷訊息的本地 SQLite 資料庫,正在以每年 640 TB 的速度把資料寫進使用者的 SSD。換算下來,1 TB 消費級 SSD 的 TBW(總寫入位元組)額度大約在 600 TBW 左右,等於不到一年就把整顆硬碟的官方保固壽命用完。
這個 Bug 最早由 GitHub 用戶 1996fanrui 在 6 月 14 日提出,截至 6 月 22 日已經累積 209 個表情反應、24 條留言,並被 Hacker News 推上首頁 258 分、142 條討論。Notebookcheck 也於 6 月 22 日以「OpenAI Codex has a bug that could kill your SSD in under a year」為題做了報導。
數據有多誇張
發報者在自己的機器上跑了 21 天,磁碟總寫入量已經達到 37 TB。以此速率外推,一年大約是 640 TB——對一顆 1 TB SSD 來說,相當於每年把整顆硬碟的容量寫入 640 次。
更可怕的是「寫入放大(write amplification)」效應。事件回報者在 15 秒內觀察到資料表新增了 36,211 筆紀錄,但實際保留的列數幾乎沒變(681,774 → 681,774),代表 SQLite 一直在「插入 → 建立索引 → 寫入 WAL → 修剪」的循環中打轉。表面上看資料庫大小只有 1 GB 左右,但磁碟實際承受的寫入量遠高於檔案體積。
71% 的日誌是 TRACE 等級的無用雜訊,剩下 25% 是 OpenTelemetry 的鏡像遙測事件。過濾這兩類就能砍掉約 96% 的日誌體積,卻不會真正影響除錯能力。
兇手是這行程式碼
根據 Issue 內的分析,問題根源在 SQLite 回饋日誌的安裝方式:
Targets::new().with_default(Level::TRACE)
這代表 Codex 把所有目標(target)都預設成 TRACE 等級——TRACE 是 Rust 生態裡最低階、最雜訊的日誌層級,理論上只該在開發除錯時打開。它記錄了從 tokio-tungstenite 內部的 WebSocket 握手細節、hyper_util 的 HTTP 處理、inotify 對 passwd 與 ld.so.cache 的檔案開啟事件……全都寫進本地 SQLite。
更麻煩的是,這個日誌層級不吃標準的 RUST_LOG 環境變數。也就是說,連熟悉 Rust 工具鏈的開發者也找不到乾淨的方法把噪音關掉。
Codex 把「診斷用日誌」當成「無腦全寫」處理,等同把每台使用者的筆電當成 OpenAI 內部的 log aggregator。
為什麼這件事重要
這個 Bug 不只是「程式寫得不乾淨」這麼單純,它觸及三個結構性問題。
第一,硬體壽命是隱形成本。 2026 年的消費級 SSD 主流是 1 TB 至 4 TB 容量,TBW 額度依等級從 200 TBW(QLC)到 1,200 TBW(TLC 高階)不等。Codex 一年寫 640 TB,會把低階 SSD 在使用 4 個月內就逼近額度;就算換高階 TLC,也撐不到兩年。使用者根本沒有同意這項成本。
第二,「Agent 寫滿你硬碟」是新型態的運算風險。 傳統桌面軟體的本地快取頂多佔個位數 GB;AI Agent 為了「可觀察性」與「遙測鏡像」狂寫本地狀態,卻又把「關不掉」當作預設行為。這是 AI 工具時代的「權限邊界」新問題——使用者連自己硬碟的寫入配額都被 AI 工具事先透支了。
第三,社群已經有解法,但 OpenAI 沒進主線。 Issue 留言串裡至少出現三個可行的修補方向:把 default 從 TRACE 改成 WARN 或加 filter(PR-ready branch)、用 SQLite trigger 攔截 INSERT、或直接把 ~/.codex/logs_2.sqlite symlink 到 tmpfs 讓寫入落在 RAM。但截至 6 月 22 日,OpenAI 仍未在 main 分支合併任何修正。
數據解讀與質疑
640 TB 是推估不是測量值。 發報者只有 21 天的實測樣本(37 TB),640 TB 是線性外推。實際年寫入量取決於 Codex 的使用強度(使用越活躍 → log 越多),重度用戶可能更高,輕度用戶可能更低。Notebookcheck 引述同一個數字時,沒有交代這是上限值還是平均值。
「不到一年燒掉 SSD」是情境性結論。 TBW 是保固額度,SSD 在額度耗盡後並不會立即壞掉——只是失去保固。實務上多數 SSD 在超過 TBW 後還能用,只是掉速與掉資料風險提高。但對依賴 TBW 額度做企業資產盤點的 IT 部門來說,這是會計上的實質損失。
「忽略 RUST_LOG」這個說法需要更多證據。 從原始碼結構看,Codex 的 SQLite feedback log sink 與 standard tracing subscriber 是兩條獨立路徑,RUST_LOG 本來就不會影響它——這是 tracing 框架的設計,不是 OpenAI 故意違規。Issue 用「ignore RUST_LOG」的措辭容易誤導讀者以為這是單一開關能解決的問題。
臨時解法
在 OpenAI 推出正式修補前,社群整理出三個可立即採取的步驟:
- Linux / macOS:把
~/.codex/logs_2.sqlitesymlink 到/tmp/或tmpfs,讓寫入落在記憶體而不是 SSD。mv ~/.codex/logs_2.sqlite /tmp/logs_2.sqlite ln -s /tmp/logs_2.sqlite ~/.codex/logs_2.sqlite - 跨平台(需先安裝
sqlite3CLI):建立 INSERT trigger 攔截日誌寫入。sqlite3 ~/.codex/logs_2.sqlite \ "CREATE TRIGGER IF NOT EXISTS block_log_inserts \ BEFORE INSERT ON logs BEGIN SELECT RAISE(IGNORE); END;" - 定期清 WAL:用
VACUUM FULL把資料庫實際大小從數 GB 縮回數十 MB(單次可見 27 GB → 73 MB 的回報案例)。
不過這三個都是治標——治本仍須 OpenAI 在 main 分支把 with_default(Level::TRACE) 換成合理的 filter。
後續發展
6 月 22 日截稿前,OpenAI 已在內部倉庫有對應的修補討論,但 Issue 本身仍維持 open 狀態,未被任何 OpenAI 員工回應承認。HN 討論串裡有用戶提到,Anthropic 的 Claude Code 也有同類問題(~/.claude/logs 大量寫入),代表這可能不是 Codex 單一個案,而是 AI 編碼 Agent 在「可觀察性 vs 使用者資源」這個 trade-off 上的產業結構性盲點。
Siami 將持續追蹤 OpenAI 是否在 6 月底前合併社群提交的修補 PR。
網友熱門留言 (5)