Codex CLI + full-auto 沙箱写盘问题复现与修复:--sandbox read-only、tmpfs 挂载、inotify 限速三种保护方案

Codex CLI + full-auto 沙箱写盘问题复现与修复:--sandbox read-only、tmpfs 挂载、inotify 限速三种保护方案
上周三晚上十一点多我正用 Codex CLI 的 full-auto 模式跑一个批量重构任务——大概 40 多个文件的 import 路径要统一改掉。跑了大概二十分钟我听到笔记本风扇开始狂转打开 iotop 一看Codex 的沙箱进程在以 180MB/s 的速度往/tmp写东西。当时我的 512G SSD 剩余写入寿命已经只剩 78% 了吓得我直接kill -9。Codex CLI 在 full-auto 模式下会触发高频文件写入根因是沙箱的 allow-write 策略默认覆盖了整个/tmp目录且没有写入速率限制导致模型生成的中间文件diff patch、执行日志、临时脚本在循环任务中无限堆积。解决方案有三种收紧沙箱为 read-only 再显式开白名单、用 tmpfs 内存盘隔离临时写入、或用 inotify 脚本做写入限速熔断。这篇适合谁在用 Codex CLI full-auto 模式跑批量任务发现磁盘 IO 异常高的人想搞清楚 Codex 沙箱到底允许写哪些路径、怎么收紧权限的开发者Linux 服务器上部署 Codex CLI 做 CI/CD 自动修复需要保护磁盘的 DevOps单纯好奇AI 写代码怎么还能把 SSD 写穿的吃瓜群众整体流程复现问题——确认 full-auto 模式下高频写盘的触发条件定位根因——分析沙箱 writable_roots 默认策略和/tmp未隔离的问题方案一--sandboxread-only 显式白名单最安全方案二tmpfs 内存盘挂载替代物理磁盘最省 SSD方案三inotify 监控 写入限速熔断更灵活根据场景选方案graph TD A[Codex full-auto 启动] -- B{沙箱写入策略} B --|默认: CWD /tmp 可写| C[中间文件无限堆积] C -- D[SSD 高频写入 180MB/s] D -- E{选择保护方案} E -- F[方案一: read-only 白名单] E -- G[方案二: tmpfs 内存盘] E -- H[方案三: inotify 限速熔断]先说结论方案保护效果性能影响适合场景read-only 白名单最强彻底杜绝意外写入可能中断任务需重跑生产 CI/CD、不信任任务内容tmpfs 挂载强写入不落盘占用内存建议预留 2G开发机日常使用inotify 限速中等超阈值才熔断几乎无需要保留写入能力但防失控第一步复现高频写盘的触发条件触发条件挺具体的循环性任务 full-auto 默认沙箱配置。用下面这条命令可以稳定复现codex --approval-mode full-auto refactor all files in src/ to use absolute imports, fix each file one by one跑起来之后用iotop -a -o -P-a累计模式-o只显示有 IO 的进程-P只显示进程不显示线程观察大概 3 分钟后写入速率就会飙上去。原因是 Codex 对每个文件生成 diff patch 写到/tmp/codex-*目录而循环任务不会清理前一轮的临时文件。实测数据40 个文件的重构任务跑完/tmp下堆了 2.3GB 的临时文件全是.patch和.log。第二步定位根因——沙箱默认策略过宽查看当前配置cat ~/.codex/config.yaml配置文件中sandbox.writable_roots默认包含两个路径当前工作目录CWD和/tmp。问题就出在/tmp这里——它没有容量限制也没有速率限制。注意sandbox.writable_roots是本文使用的配置字段名实际字段名称请以codex --help或官方文档为准不同版本可能有差异。macOS 上的沙箱是 Apple Seatbeltsandbox-execLinux 上是 Docker 或 Landlockseccomp。不管哪个平台/tmp都被标记为可写。这个设计本身没错——很多构建工具确实需要写临时文件——但缺了一个写入总量上限的兜底。第三步方案一read-only 沙箱 显式白名单把沙箱收紧到只读然后只开放确定需要写入的目录# ~/.codex/config.yaml sandbox: writable_roots: - /home/user/myproject/src这样/tmp就不可写了。如果任务确实需要写临时文件它会报错PermissionError: [Errno 1] Operation not permitted: /tmp/codex-abc123/patch.diff看到这个报错说明沙箱在正常工作。如果任务必须写临时文件往writable_roots加一个专用子目录就行别给整个/tmpsandbox: writable_roots: - /home/user/myproject/src - /tmp/codex-limited然后手动建这个目录并设置配额下一步讲。第四步方案二tmpfs 内存盘挂载让 Codex 继续写/tmp但/tmp本身是内存盘不落物理磁盘SSD 写入量大幅降低。sudo mount -t tmpfs -o size2G tmpfs /tmp/codex-sandbox然后把 config 里的 writable_roots 指向这个挂载点sandbox: writable_roots: - /home/user/myproject/src - /tmp/codex-sandboxtmpfs 满了之后写入会直接失败相当于自带容量熔断。2G 对绝大多数重构任务够用了。实测跑了一周最大一次用了 1.4G。重启后 tmpfs 会丢失想持久化就加到/etc/fstabtmpfs /tmp/codex-sandbox tmpfs size2G,mode1777 0 0第五步方案三inotify 监控 写入限速熔断不改沙箱配置在外面套一层监控。写入事件累计超过阈值就自动终止 Codex 进程。先装 inotify-tools大多数 Linux 发行版都有包sudo apt install inotify-tools然后写个监控脚本codex-guard.sh#!/bin/bash # 累计写入事件超过 THRESHOLD 次则触发熔断 # 注意这是累计计数模式不是滑动时间窗口如需滑动窗口请自行扩展 THRESHOLD500 LOGFILE/var/log/codex-guard.log # 记录 Codex 进程 PID避免 pkill 模式匹配不准 CODEX_PID$1 if [ -z $CODEX_PID ]; then echo Usage: $0 codex_pid 2 exit 1 fi COUNT0 while read -r event; do COUNT$((COUNT 1)) if [ $COUNT -gt $THRESHOLD ]; then kill $CODEX_PID 2/dev/null echo [$(date)] Codex PID $CODEX_PID killed: write event count exceeded $THRESHOLD $LOGFILE exit 0 fi done (inotifywait -m -r /tmp --format %e 2/dev/null)使用方式先启动 Codex记下其 PID再启动守护脚本codex --approval-mode full-auto ... CODEX_PID$! bash codex-guard.sh $CODEX_PID与方案二相比这个方案适合需要保留完整写入能力、但想防止事件风暴的场景。计数阈值需要根据实际任务规模调整正常重构任务写入事件通常远低于 500 次。不同场景怎么选个人开发机macOS/Linux 桌面方案二 tmpfs 最省心。挂载一次就完事不用改工作习惯SSD 写入量大幅降低。内存 16G 以上的机器拨 2G 出来压力不大。CI/CD 服务器方案一 read-only 白名单。生产环境不能容忍任何意外写入宁可任务失败重跑也不要磨盘。CI 里 Codex 用的 o4-mini 模型 input $1.10/M tokens以 OpenAI 官方定价为准请自行核实当前价格跑一次重构任务大概 ¥0.3–0.8失败重跑成本可以忽略。需要保留完整写入能力但怕失控方案三 inotify。比如你在用 Codex 做代码生成任务生成的文件本身就需要落盘但想防止循环写入风暴。混合方案我现在用的tmpfs inotify 双保险。tmpfs 保护 SSDinotify 在内存盘快满之前就熔断避免 OOM。踩坑记录 / 常见问题 FAQQ: Codex full-auto 模式下 npm install 会被 read-only 沙箱拦截吗会。npm install要往node_modules写文件如果你的 writable_roots 没包含项目目录就会报PermissionError。解决办法是把项目根目录加到白名单里——反正你本来就要让 Codex 改这个目录的代码。Q: macOS 上 sandbox-exec 报Operation not permitted怎么办按顺序查① 确认 Codex CLI 支持的 macOS 最低版本以官方文档为准② 确认/usr/bin/sandbox-exec存在③ 检查 SIP 状态csrutil status确认 SIP 处于开启状态——SIP 被关闭时 sandbox-exec 的强制约束可能失效表现为沙箱限制不生效而非报错。我上个月在一台 Hackintosh 上踩过这个坑折腾半天发现是装黑苹果时把 SIP 关了。Q: tmpfs 方案会不会导致 Codex 任务中途 crash会。tmpfs 满了写入会返回ENOSPCNo space left on deviceCodex 进程会直接退出。所以 size 要给够建议 2G 起步。如果你的任务经常处理大型 monorepo几百个文件给 4G。Q: Linux 上 Landlockseccomp 方案内核版本不够怎么办内核版本低于 5.13 的话 Landlock 不可用Codex 会 fallback 到 Docker 容器沙箱。如果 Docker 也没装会报Error: Docker daemon not running。这时候要么升内核要么装 Docker要么退回auto-edit模式手动确认写入操作。Q: 怎么确认我的 Codex 版本支持 writable_roots 配置跑codex --version看版本号。2025 年 4 月之后发布的版本均支持Codex CLI 于 2025 年 4 月底开源。老版本如果在 config.yaml 里写了sandbox.writable_roots会被忽略但不报错——静默失败比较难排查建议升到最新版再配置。小结Codex CLI full-auto 模式的高频写盘问题根源在于默认策略对/tmp的写入没有总量限制。循环任务加上无限制的临时文件堆积对 SSD 损耗较大。三种方案各有适用场景个人日常用 tmpfs inotify 双保险跑了快两周再没出现过写入风暴。磁盘健康度稳定在 78% 没再掉——虽然这个数字本身已经让我有点焦虑了。