观察时间:2026 年 6 月 23 日。 这两天 Codex 社区里最值得警惕的不是某个新功能,而是一个更基础的问题:本地 Codex 可能在后台持续写 SSD。
这个问题听起来像小毛病,但它不是小毛病。
普通软件写一点日志,最多占空间;长期运行的 AI Agent 如果持续高频写 SQLite、WAL、日志和会话状态,就会带来三个后果:磁盘空间被吃掉,系统 I/O 变慢,SSD 写入寿命被无意义消耗。
更关键的是,这类问题暴露了一个新现实:AI Agent 正在从一次性命令变成常驻工作系统,但很多本地持久化、日志、重试和自我保护机制,还没有按常驻系统的标准设计。
这篇文章按四件事拆开:
- 这次到底是什么问题。
- 根因大概率在哪里。
- 我自己是否中招。
- 现在应该怎么处理。
先给结论
截至 2026 年 6 月 23 日,我看到的公开证据里,Codex 相关的 SSD 过写不是一个单点 bug,而是一组同源问题:
~/.codex/logs_2.sqlite反馈日志写入过多,尤其是 TRACE、WebSocket payload、OpenTelemetry mirror log。~/.codex/goals_1.sqlite在 goal 功能下可能出现小数据库、大量 WAL 和 fsync 写入放大。- Codex Desktop / WSL / Windows 下还有本地状态、runtime 部署、文件监听和 app-server 写入偏高的问题。
- 旧版本里还出现过
codex-tui.log无限增长,磁盘写满后触发二次错误的情况。
当前最直接的行动是:升级到 @openai/codex 0.142.0 以上,观察是否还有持续写入;如果正在被写爆,先关闭 Codex,再清理或迁移日志文件。
但我不认为升级就能结束所有问题。0.142.0 已经合并并发布了两项降低 persistent-log churn 的修复,另一个 follow-up PR 也在 6 月 23 日合并,但截至我核对 npm 时,npm 最新仍是 0.142.0。也就是说,问题正在被修,但“本地 Agent 应该有写入预算、日志上限、重试退避和用户可见诊断”这件事,还没有真正完成。
这次最核心的问题:logs_2.sqlite
最集中的讨论来自 openai/codex 的 #28224。这个 issue 报告称,Codex 会持续向本地 SQLite 反馈日志数据库写入:
~/.codex/logs_2.sqlite
~/.codex/logs_2.sqlite-wal
~/.codex/logs_2.sqlite-shm
报告者给出的量级非常夸张:约 21 天机器 uptime 后,主 SSD 写入约 37TB,并推算到全年约 640TB。这不是说每个用户都会达到这个量级,而是说明在某些使用模式下,Codex 的本地日志写入可以从“开发工具正常开销”变成“硬件寿命风险”。
更值得注意的是它的写入方式。
logs_2.sqlite 里保留的行数可能并不持续增长,因为系统会插入、保留、再裁剪。但 SQLite 的自增 ID、WAL 和底层写入仍然不断前进。也就是说,用户看到的数据库大小不一定等于真实写入量。
这就是这类 bug 危险的地方:文件大小看起来稳定,不代表 SSD 没有被持续写。
为什么会发生:日志系统把低价值事件当成高价值数据持久化
从公开 issue 和修复 PR 看,最主要的根因是 persistent log sink 过于吵。
PR #29432 的标题是 “Stop logging every Responses WebSocket event”。它说明此前每个成功的 Responses WebSocket event 会产生多条本地记录,包括完整 payload 的 TRACE 日志和 OpenTelemetry mirror event。忙碌线程下,这些记录会很快填满日志分区,并造成持续 SQLite insert-and-prune churn。
PR #29457 进一步过滤 noisy targets,明确提到本地 SQLite log sink 曾经对所有 target 启用 TRACE,导致依赖日志、codex_otel.log_only 和 codex_otel.trace_safe 等重复遥测记录被持久化。
PR #29599 是 6 月 23 日合并的后续修复,继续处理 bridged log events 进入 SQLite 的问题。
这三件事合起来看,问题不只是“日志太多”,而是日志分层错了。
对开发者来说,TRACE 日志用于临时排障可以理解;但如果默认把高频网络事件、依赖库噪声、原始 payload、mirror telemetry 都写进本地 SQLite,而且还在后台 insert 后再 prune,这就不是调试,而是把 SSD 当成吞吐缓冲区。
我的判断是:
AI Agent 的本地日志默认值必须更接近生产系统,而不是更接近工程师临时 debug。
因为 Codex 不是普通 CLI。它会长时间运行,会持有会话,会自动压缩上下文,会调用工具,会管理多个线程,还可能在用户离开电脑后继续工作。它的日志策略必须有硬上限。
第二类问题:goals_1.sqlite 的写入放大
另一个值得关注的是 #27911,报告的是 goal 功能产生的 goals_1.sqlite 写入放大。
这个 issue 里提到,数据库文件本身可能只有 4KB 到 25KB,但进程层面却能看到持续约 11MB/s 的写入。报告者认为原因是 WAL churn 和 fsync,建议对 goal 状态持久化做 debounce、coalesce、批处理,或者降低这个低价值状态的持久化强度。
这个问题本质上和 logs_2.sqlite 一样:业务数据很小,但持久化频率过高,最终放大成硬件写入。
它提醒我们一件事:对 Agent 来说,状态不只是最终回答。任务进度、goal heartbeat、token 统计、上下文压缩、工具调用日志、UI sidebar 元数据都可能被保存。只要保存策略没有节流,再小的数据也会变成高频写入。
第三类问题:Desktop、WSL 和 runtime 部署
除了两个主问题,还有几个旁支值得看。
Desktop macOS issue #21007 报告了 Codex Desktop UI 卡顿,同时 macOS 诊断显示 Codex 原生进程在约 648 秒内写入约 2.1GB file-backed memory dirty data。
WSL issue #27020 报告 Windows 11 + WSL2 + VS Code / CLI 场景下,Codex 相关进程成为主要累计磁盘写入者之一,并造成 Windows 磁盘 active time 偏高。
Windows runtime issue #28093 则指向非 ASCII / CJK 用户路径下,Codex 可能重复部署 cua_node runtime,反复写入大量 runtime 文件。
这些问题不一定和 logs_2.sqlite 是同一个 bug,但方向一致:Codex 正在变成一个跨 CLI、Desktop、IDE、App Server、Computer Use 的本地系统。系统越复杂,本地状态、缓存、日志、runtime、文件 watcher 就越多。任何一个环节缺少上限,都会被长时间使用放大。
我自己有没有中招
我没有只看 issue,也查了我这台机器。
我当前本机结果是:
codex-cli 0.140.0
~/.codex 总大小:842M
~/.codex/logs_2.sqlite:320M
~/.codex/logs_2.sqlite-wal:4.1M
~/.codex/goals_1.sqlite:24K
~/.codex/goals_1.sqlite-wal:52K
我没有读取日志正文,只查了聚合字段:
logs rows:39401
estimated log bytes:71.77MB
time window:2026-06-15 到 2026-06-23
TRACE:18571 rows / 47.83MB
INFO:16213 rows / 20.14MB
DEBUG:4104 rows / 3.47MB
WARN:489 rows / 0.31MB
ERROR:24 rows / 0.02MB
然后我做了一个 20 秒窗口观察:
before: rows=39401, max_id=23359751, estimated=71.77MB
after: rows=39401, max_id=23360027, estimated=71.77MB
delta: rows=0, max_id=276
这个结果很有代表性:保留行数没有变,估算内容大小也没有变,但 max_id 在 20 秒内增加了 276。也就是说,我这台机器确实存在 insert-and-prune 类型的日志 churn。
我的结论是:
我没有看到灾难级写爆 SSD,但已经属于“轻度中招”。
尤其是我还在 codex-cli 0.140.0,而 npm 当前最新已经是 0.142.0。所以我的处理优先级很明确:先升级,再观察 logs_2.sqlite 和 max(id) 是否还在快速增长。
你怎么判断自己是否中招
如果你是 macOS / Linux 用户,可以先看版本:
codex --version
npm view @openai/codex version
再看本地 Codex 目录大小:
du -sh ~/.codex ~/.codex/log ~/.codex/logs_*.sqlite* ~/.codex/goals_*.sqlite* 2>/dev/null
如果你装了 sqlite3,可以只查聚合,不读日志正文:
sqlite3 ~/.codex/logs_2.sqlite \
"select count(*), max(id), round(sum(estimated_bytes)/1024.0/1024.0,2) from logs;"
等 20 秒,再查一次:
sqlite3 ~/.codex/logs_2.sqlite \
"select count(*), max(id), round(sum(estimated_bytes)/1024.0/1024.0,2) from logs;"
如果 count(*) 不变但 max(id) 快速增加,就说明后台还在持续插入然后裁剪。这个时候不要只看数据库文件大小,因为文件大小可能已经稳定在一个区间,但底层写入还在发生。
还可以查日志等级分布:
sqlite3 ~/.codex/logs_2.sqlite \
"select level, count(*), round(sum(estimated_bytes)/1024.0/1024.0,2) from logs group by level order by sum(estimated_bytes) desc;"
如果 TRACE 占比很高,且数据库、WAL 或 max(id) 增长明显,就基本符合这次问题的典型形态。
Windows 用户需要重点看两个位置:
%USERPROFILE%\.codex\logs_2.sqlite
%USERPROFILE%\.codex\logs_2.sqlite-wal
%LOCALAPPDATA%\OpenAI\Codex\runtimes\cua_node
如果你是 CJK / 非 ASCII Windows 用户名,还要特别注意 cua_node runtime 是否反复生成。这个问题在公开 issue 中已有报告。
现在怎么解决
第一步,升级。
npm install -g @openai/codex@latest
codex --version
我核对到的 npm 最新版本是 0.142.0。GitHub release rust-v0.142.0 在 changelog 中明确写到,已经通过 #29432 和 #29457 降低 persistent-log churn。
第二步,重新观察。
升级后不要只确认版本号。最好重新做一次 20 秒或 60 秒 max(id) 快照。如果 max(id) 基本不动,说明日志 churn 已经大幅缓解。如果它还在明显增长,可能需要等待包含 #29599 的下一版,或临时处理。
第三步,清理已经膨胀的日志。
如果 logs_2.sqlite* 已经很大,最稳妥的做法是:
- 退出 Codex CLI、Desktop、IDE extension 和相关 app-server。
- 备份或删除
~/.codex/logs_2.sqlite*。 - 重启 Codex,让它重新创建日志数据库。
这些文件主要是本地反馈和诊断日志,不是你的项目源码;类似处理也出现在 #26374 的 workaround 描述里。但在动 ~/.codex 之前,仍然建议先备份,尤其是你不确定哪些文件保存了会话状态。
第四步,临时关闭 goals。
如果你命中的是 goals_1.sqlite 写入放大,可以在 ~/.codex/config.toml 中临时关掉 goals:
[features]
goals = false
或者在启动时使用对应的 disable 方式。这个 workaround 来自 #27911 的公开报告。
第五步,谨慎看待社区 workaround。
有用户在 issue 中给出过 SQLite trigger,用 BEFORE INSERT 阻止写入日志。这个办法能立刻降低 SQLite 插入,但它是非官方 workaround,而且可能影响 Codex 后续诊断能力。
更重要的是,不要随便运行 npx xxx@latest 这种会修改 ~/.codex 的第三方脚本。它解决的是一个本地状态问题,但自己也引入供应链风险。真要用社区工具,至少固定版本、先 dry-run、先备份。
我对这件事的判断
这次事故真正刺耳的地方,不是 OpenAI 某个版本写了太多日志。软件都会有 bug。
真正刺耳的是:AI Agent 工具正在拥有越来越高的本地权限、越来越长的运行时间、越来越复杂的后台状态,但它们的本地资源治理还没有跟上。
开发者工具过去多数是前台交互:命令跑完就结束,日志写在当前项目,出问题用户马上能看到。现在的 Agent 不一样。它会后台做任务,会开 app-server,会维护 session,会写 SQLite,会压缩上下文,会操作浏览器,会调工具,会跨线程运行。它已经接近一个小型本地操作系统组件。
这意味着它必须具备几条底线:
- 日志必须有硬上限,不能默认无限增长。
- 高频状态必须 debounce / batch,不能每个 heartbeat 都 fsync。
- 重试必须有退避和停止条件,usage limit 这类错误不应该 tight loop。
- 本地诊断必须用户可见,用户应该知道 Codex 正在写什么、为什么写、写了多少。
- 默认配置必须保护普通用户,不是让用户去 GitHub issue 里找 SQLite trigger。
从这个角度看,Codex 这次不是单纯的“SSD bug”,而是 AI Agent 产品化过程中的一次工程提醒:模型能力越强,周边系统越不能粗糙。
未来优秀的 AI Coding 工具,不只是回答更聪明,而是更克制地使用用户机器。它应该知道什么时候该写,什么时候该停,什么时候该告诉用户“我正在消耗你的本地资源”。
我的处理建议
如果你现在正在用 Codex,我建议按这个顺序处理:
- 先升级到最新版本。
- 查
~/.codex/logs_2.sqlite*和~/.codex/goals_1.sqlite*大小。 - 用
max(id)做 20 秒或 60 秒窗口观察。 - 如果日志已经很大,退出 Codex 后清理
logs_2.sqlite*。 - 如果 goals 写入异常,临时关闭 goals。
- Windows / WSL 用户额外检查 runtime 目录和 WSL 磁盘 active time。
- 不要盲目运行未固定版本的社区修复脚本。
我自己的状态是:轻度中招,尚未写爆;主要风险是当前版本落后于修复版本,且 logs_2.sqlite 仍有 insert-and-prune churn。
这件事也改变了我对 Agent 工具的使用习惯。以后我会把 ~/.codex、~/.claude、~/.cursor 这类目录当成长期运行服务的状态目录来监控,而不是当成普通 CLI 缓存。
AI 工具越像同事,越要像基础设施一样被检查。
参考来源
- openai/codex #28224: Codex SQLite feedback logs can write ~640 TB/year
- openai/codex #27911: goals_1.sqlite write amplification
- openai/codex #24275: Codex Desktop rapidly grows logs_2.sqlite / WAL
- openai/codex #26374: app-server feedback log sqlite grows unbounded
- openai/codex #23722: codex-tui.log grew to 67GB after retry loop
- openai/codex #21007: macOS Desktop UI lag with excessive disk writes
- openai/codex #27020: Windows WSL2 severe disk I/O
- openai/codex #28093: Windows cua_node runtime repeated writes
- openai/codex PR #29432: Stop logging every Responses WebSocket event
- openai/codex PR #29457: Filter noisy targets from persistent logs
- openai/codex PR #29599: Stop persisting bridged log events
- openai/codex release rust-v0.142.0
- OpenAI Codex manual