用触发器阻止 Codex SQLite 日志增长
内容提要
Codex 将本地日志写入 logs_2.sqlite,导致数据库膨胀超 1GB,且无公开的日志保留或大小限制配置。作者用 SQLite 触发器拦截 logs 表插入以阻止新日志写入,并给出 Windows 版本、恢复写入及 VACUUM 清理旧日志的方法。该方案只是临时止损,会削弱本地调试能力,长期仍需官方提供日志保留设置。
延伸解读
为什么官方配置无法控制日志数据库
文章指出,Codex 的公开配置选项对 logs_2.sqlite 几乎无效:RUST_LOG 只能降低日志详细程度,log_dir 仅控制纯文本 TUI 日志,history.max_bytes 只作用于 history.jsonl。没有公开的保留策略、最大大小或日志模式设置。因此,即使调低日志级别,SQLite 日志表仍会持续写入 TRACE、DEBUG 和 INFO 行,导致数据库膨胀。这解释了为什么需要绕过官方配置,直接用 SQLite 触发器拦截插入。
触发器方案的代价与适用场景
用触发器阻止插入是一种临时止损,优点是无需修改 Codex 代码、无需等待官方发布、也无需后台清理进程。但代价是 logs_2.sqlite 不再记录新的本地日志,会削弱本地调试能力。文章建议在需要日志时先删除触发器,复现问题后再重新添加。因此,该方案适合磁盘空间紧张且暂时不需要本地日志的用户,而不适合依赖日志排查问题的开发场景。
清理旧日志的正确顺序与注意事项
触发器只能阻止新日志写入,无法缩小已膨胀的数据库。文章给出的清理步骤是:先退出 Codex,然后执行 WAL 检查点、删除 TRACE 和 DEBUG 级别日志、删除三天前的 INFO 日志,最后执行 VACUUM。如果 Codex 仍在运行,SQLite 可能报 database is locked,这是预期现象,退出后重试即可。注意,删除操作会永久移除旧日志,执行前应确认不再需要这些调试信息。
上游修复进展与长期依赖风险
文章提到,Codex 0.142.0 虽减少了一些高流量日志源,但并未让 SQLite 日志接收器遵循 RUST_LOG,也未增加可用的日志级别、采样或保留设置。在 0.144.5 上仍能复现日志数据库一周增长约 529MB 甚至达到 2.795GB 的情况,上游问题 #31142 仍未关闭。因此,触发器方案目前仍是有效的临时手段,但长期来看,官方提供日志保留或最大大小设置才是根本解决办法。
Q&A
Codex 的 logs_2.sqlite 数据库为什么会膨胀到超过 1GB?
因为 Codex 将本地日志写入 ~/.codex/logs_2.sqlite,TRACE、DEBUG 和 INFO 级别的日志行持续插入 SQLite,造成不必要的磁盘占用和 IO。公开配置中缺少针对该数据库的保留、大小限制或日志模式选项,RUST_LOG、log_dir 和 history.max_bytes 都无法控制它。
如何用 SQLite 触发器阻止 Codex 继续写入新日志?
在 ~/.codex/logs_2.sqlite 中执行:CREATE TRIGGER IF NOT EXISTS block_log_inserts BEFORE INSERT ON logs BEGIN SELECT RAISE(IGNORE); END; 这样任何插入 logs 表的操作都会被忽略。Windows 下路径为 $env:USERPROFILE\.codex\logs_2.sqlite,命令相同。
如何验证阻止日志插入的触发器已经生效?
执行测试插入并对比行数:先查询 SELECT count(*) FROM logs;,再插入一条测试记录,然后再次查询行数并检查 target='trigger_test' 的记录数。如果行数不变且 trigger_test 为 0,说明触发器正常工作。
如果之后需要恢复 Codex 的日志写入,应该怎么做?
删除触发器即可恢复:sqlite3 ~/.codex/logs_2.sqlite "DROP TRIGGER IF EXISTS block_log_inserts;"。Windows PowerShell 下使用 $db = Join-Path $env:USERPROFILE ".codex\logs_2.sqlite"; sqlite3 $db "DROP TRIGGER IF EXISTS block_log_inserts;"。
已经膨胀的 logs_2.sqlite 数据库如何清理和压缩?
先退出 Codex,然后执行:PRAGMA wal_checkpoint(TRUNCATE); DELETE FROM logs WHERE level IN ('TRACE','DEBUG'); DELETE FROM logs WHERE level = 'INFO' AND ts < strftime('%s','now','-3 days'); VACUUM;。如果 Codex 仍在运行,SQLite 可能报 database is locked,退出后重试即可。
用触发器阻止日志写入有什么缺点和局限性?
这只是本地临时止损,并未修复 Codex 的日志系统。缺点是 logs_2.sqlite 不再包含新的本地日志,会削弱本地调试能力。需要日志时得先删除触发器、复现问题,再重新添加触发器。长期来看,Codex 官方应提供日志数据库的保留或最大大小设置。