值班台突然出现 Nginx 502,最危险的不是让 Codex 参与排查本身,而是直接给它生产机的 root 权限、开放完整文件系统和网络,再让它自由修改 /etc、重启服务。本文涉及的值班场景只是示例,并非作者亲历记录;它对应了 CSDN《【AI智能体】Codex 实现AI自动化运维实战操作详解》所代表的自动化运维需求:用 AI 收集证据、生成变更,再由确定性的部署流程落地。
更稳妥的路径是:先用只读模式定位问题,再在 Git 工作树中生成可审查的变更,最后用独立的语法检查、测试、健康检查和回滚流程确认结果。不要把 codex exec 当成 root shell;官方文档也将非交互执行、沙箱限制和审批策略设计为不同层次的控制点。
codex exec --sandbox read-only \
"分析当前仓库内的 Nginx 配置与日志,定位 502;不要修改文件,只给出证据和验证建议。"
这条命令只允许诊断。它不会改仓库、不会重载 Nginx,也不会因为模型说“问题已解决”就自动通过发布流程。真正需要权限时再逐级开放,并让每一步都可检查、可阻止、可回滚。
codex exec 和交互式 codex 该怎么选?
交互式 codex 和 codex exec 的区别不只是界面不同。前者适合步骤尚未确定、需要边执行边确认的排障;后者接收一项边界明确的任务,完成后返回消息、事件和进程状态,更适合脚本与流水线。
| 执行方式 | 适合场景 | 主要边界 | 放行依据 |
|---|---|---|---|
交互式 codex |
临时排障、步骤不明确、包含系统级操作 | 依赖当前沙箱和审批配置,任务边界可随对话变化 | 人工确认每一步风险 |
codex exec --sandbox read-only |
日志巡检、配置检查、重复诊断 | 不写文件,读取仍受 Linux 用户权限限制 | 退出状态、事件输出和外部检查 |
codex exec --sandbox workspace-write |
Git 工作树内的代码或配置修改 | 写入集中在工作区,不代表能修改 /etc |
diff、语法检查、测试 |
| CI 加受控部署流程 | 无人值守执行和正式发布 | Codex 只生成补丁或制品,外层系统决定是否应用 | 流水线门禁与审计记录 |
交互式 codex 适合人在回路中处理未知问题。比如 Nginx 502 可能来自配置语法、上游进程、连接超时、DNS、TLS 或负载均衡,排查路径会随证据变化,这时保留人工审批更合理。
codex exec 更适合重复且可以自动判定边界的任务,例如每天扫描日志、检查某类配置是否偏离基线,或者在仓库中按既定规则生成配置差异。无人值守时必须避免任务停在审批提示上,同时仍要保留沙箱限制。
Linux 上运行前先确认什么?
先确认命令位置、CLI 版本、当前目录和运行用户,不要从旧教程直接复制安装命令。Codex CLI 是在本地终端中运行的工具,社区教程可用于了解 Linux 使用背景,但安装方式和参数应以当前官方仓库为准。
command -v codex
codex --version
codex exec --help
pwd
id
git rev-parse --show-toplevel 2>/dev/null || true
git status --short
这些输出可用来核对几个常见问题:command -v 确认交互式 shell 能否找到程序;codex --version 用于确认实际安装版本;codex exec --help 用来核对当前版本是否支持 --sandbox、--ask-for-approval、--json 等参数;pwd 和 Git 根目录用于确认执行目录与工作树是否正确,避免 Codex 在错误的工作树中执行任务。
运行用户同样重要。不要为了绕过文件权限而直接切换到 root。使用 sudo 后环境的 PATH 也可能与当前 shell 不同,服务账户和 CI Runner 的 HOME、工作目录及环境变量也可能不同。排查参数不生效时,先比较实际执行环境,不要先扩大权限。
脚本和 CI 怎么判断任务真的完成了?
codex exec 可以通过命令行参数接收任务,也可以从标准输入读取。最终消息适合阅读,JSONL 事件适合机器处理,退出状态则用于判断 CLI 执行本身是否失败。具体选项以当前版本的 codex exec --help 为准。
下面是一个保留事件、最终消息和退出状态的 CI 示例:
work_dir="$(mktemp -d)"
printf 'Codex artifacts: %s\n' "$work_dir"
cat >"$work_dir/task.txt" <<'PROMPT'
只读检查当前仓库中的 Nginx 配置和可访问日志,列出 502 的证据。
不得修改文件,不得执行服务重启。输出结论、证据位置和下一步检查命令。
PROMPT
codex_status=0
codex exec \
--sandbox read-only \
--ask-for-approval never \
--json \
--output-last-message "$work_dir/final.txt" \
- <"$work_dir/task.txt" \
>"$work_dir/events.jsonl" \
2>"$work_dir/stderr.log" || codex_status=$?
if [ "$codex_status" -ne 0 ]; then
printf 'codex exec failed, exit=%s\n' "$codex_status" >&2
exit "$codex_status"
fi
这里有三点需要区分。
第一,--json 输出的是 JSONL 事件流,每个事件都是独立的 JSON 记录,适合 CI 解析;--output-last-message 则把最后一条消息单独保存,便于人工复核。如果当前版本的帮助中列出了 --output-schema,还可以用它约束最终结论的字段结构,但不要依赖模型输出替代实际检查。
第二,退出状态为 0 只说明这次 Codex 执行没有以错误结束,不等于 Nginx 已经恢复,也不等于诊断结论成立。模型完全可能正常退出,却回答“证据不足,无法定位”。因此,CI 还需要执行确定性的健康检查,或者明确把“不确定”映射为阻断结果。
第三,事件、最终消息和 stderr 都可能包含主机名、路径、连接信息或日志里的凭据。应限制保存权限和保留周期,在上传 CI 制品前完成脱敏。
read-only、workspace-write 和完全访问模式怎么选?
read-only 用于诊断,workspace-write 用于仓库内可审计修改。完全访问模式及跳过审批与沙箱的选项只适合隔离的临时环境;沙箱和审批设置都不会自动赋予 Linux root 权限。
| 沙箱模式 | 适合场景 | 主要限制 |
|---|---|---|
read-only |
日志分析、配置检查、故障定位 | 不允许通过沙箱写文件,读取范围仍受操作系统权限和容器边界约束 |
workspace-write |
Git 工作树中的代码和配置修改 | 主要围绕当前工作区写入,不能自然等同于可以修改 /etc 或操作主机服务 |
danger-full-access |
隔离容器中的特殊诊断 | 绕开 Codex 文件系统沙箱,不应作为生产主机默认值 |
read-only 的“只读”并不表示它只能看到当前目录。实际能看到哪些日志和配置,仍取决于运行用户的 Unix 权限、目录 ACL、SELinux 等主机策略,以及外层容器挂载方式。反过来,它也不阻止敏感内容出现在最终回复中,因此必须同时控制输出保存和联网范围。
完全访问也不是“方便一点的 workspace-write”。它意味着放弃了一层重要保护。即便外层有容器,若挂载了生产凭据、宿主目录或 Docker socket,容器内部仍可能造成越权影响。
只想查日志和配置,允许开到什么程度?
只读排障应使用专用、非特权 Linux 账号,并使用 read-only。如果日志只有 root 或特定服务组可读,正确做法是提供经过脱敏的日志副本、为只读诊断账号授予最小范围的读取权限,或者在隔离环境中准备证据,而不是把整个 Codex 进程切换成 root。
任务提示中还应明确禁止写文件、停止或重启服务。例如:
codex exec \
--sandbox read-only \
--ask-for-approval never \
"只读检查 Nginx 错误日志、当前配置片段和监听端口;不得修改文件、不得调用 sudo、不得重启服务。每项结论必须给出证据位置。"
“禁止”不是沙箱权限的替代品。提示词用于减少模型尝试越权动作,read-only 和 Linux 权限才构成实际边界,两者应同时使用。
允许修改仓库配置,怎样限制改动范围?
仓库内修改适合使用 workspace-write,但运行目录必须明确。一个常见错误是直接在错误目录执行,结果模型确实完成了“修改”,却改到了另一份配置。
下面的变量需要替换成当前仓库的真实值,CHECK 也必须是项目已经存在的检查命令:
REPO=/absolute/path/to/repository
TARGET=nginx/site.conf
CHECK='make check'
codex exec \
--cd "$REPO" \
--sandbox workspace-write \
--ask-for-approval never \
"只修改 ${TARGET};不得触碰工作树之外的文件;修改后运行 ${CHECK};检查失败时停止,不要自行扩大修改范围。"
执行前最好确认 Git 根目录、当前分支和工作树状态,并在独立分支或临时 worktree 中操作。workspace-write 允许的是沙箱定义的受控写入,不是随意修改整台机器;--cd 指向错误目录时,它同样会忠实地写错地方。
执行任务前至少要检查:
git status --short
git diff --check
git diff --stat
git diff -- "$TARGET"
git diff --check 只能发现部分格式问题,不能替代配置解析和项目测试。已有未提交改动时,还要区分操作前基线和 Codex 新产生的差异。
任务必须联网时怎么办?
联网需求应当单独评估。包管理器下载、API 查询和远程日志读取都可能需要网络,但“允许联网”不等于“关闭全部沙箱保护”。优先把任务放在临时 CI 容器或受控代理环境中,只开放必要的目标地址;工作区可写,系统目录只读,不挂载 Docker socket,也不要携带完整生产凭据。
安装依赖时,优先使用项目已有的锁文件和容器构建流程,把依赖安装限制在项目环境内。因为一次 DNS、代理或镜像源失败,就改成完全访问并开放整台生产机的网络,通常是把局部故障扩大成全局风险。
不同 Codex 版本和沙箱配置对网络的处理方式可能不同,应结合当前安全文档与本机配置确认,不要假设 --sandbox workspace-write 会自动获得或失去某项网络权限。 需要 API 时,使用短期、限权、限域的凭据,并在任务提示、事件日志和命令输出中避免出现密钥。
要改 /etc、systemd 配置或重启服务怎么办?
生产环境更适合让 Codex 生成补丁、配置片段、systemd unit 差异、部署制品和回滚说明,再由已有的受控部署流程以适当权限应用。不要默认让模型决定何时执行 sudo、何时重载服务、失败后是否再次重试。
/etc 写入、systemd 管理权限和 Docker socket 都不是普通仓库权限。特别是 Docker socket,通常意味着接近宿主机的管理能力;把它交给一个能自由执行命令的进程,风险范围远大于单个仓库。
如果确实需要应用变更,外层流程至少应负责确认目标主机、备份当前版本、校验配置、执行重载、检查健康状态,并在失败时恢复已知良好版本。模型生成变更和模型执行生产变更,应由两套不同的门禁隔开。
有人值守和无人值守的审批策略怎么分?
审批策略决定 Codex 在什么情况下请求人工确认,并不决定它拥有哪些 Linux 权限。交互式任务可以根据风险使用 untrusted、on-failure 或 on-request;CI 则通常使用受限沙箱和 never,让越权请求直接失败并由外层流水线阻断。
| 审批策略 | 行为 | 适用位置 |
|---|---|---|
untrusted |
不在可信集合中的命令需要确认,可信集合由当前配置决定 | 有人值守、需要限制自动命令范围的任务 |
on-failure |
先自动执行,命令失败后再请求确认是否重试 | 允许尝试、但希望失败时人工介入的任务 |
on-request |
模型可以在认为必要时请求确认 | 步骤不确定的交互式排障 |
never |
不发起交互审批,需要审批的命令直接失败 | 无人值守 CI 和自动化任务 |
可信命令集合、默认策略和沙箱细节可能随版本及配置变化,使用前应查看当前文档和配置,不能照搬旧教程中的默认值。
在 CI 中,never 的意义是“不等待人工输入”,不是“不要沙箱”,更不是“自动获得系统管理员权限”。正确组合通常是:
codex exec \
--sandbox read-only \
--ask-for-approval never \
"执行只读巡检;不得修改文件、不得提权、不得重启服务。"
如果任务确实需要超出当前沙箱,CI 应该停止并交给另一个带审批的部署阶段,而不是临时放宽到完全访问。
命令失败了,怎么判断是沙箱还是 Linux 权限?
看到 Permission denied 就切换到 root,通常会跳过真正的问题。命令失败可能发生在 CLI、工作目录、沙箱、Linux 权限、依赖工具、网络、systemd 或超时等不同层次,应逐层定位。
pwd
id
printf 'PATH=%s\n' "$PATH"
command -v nginx
command -v systemctl
command -v docker
git status --short
如果 command -v codex 没有结果,先检查安装位置和当前用户的 PATH;如果提示参数不支持,则比较 codex --version 与 codex exec --help。不要为了使用新参数而直接安装来源不明的旧版或第三方二进制。
如果任务读不到目标文件,先确认当前目录是否正确、文件路径是否在允许读取的范围,以及运行用户是否具有相应权限。read-only 下写文件被拒绝是预期行为;在 workspace-write 下,工作区之外的路径也可能被沙箱阻止。此时应把产物移到工作区或生成补丁,而不是关闭沙箱。
如果错误来自 Linux 本身,例如 EACCES、EPERM,再检查文件属主、目录遍历权限、ACL 和服务账号。sudo: a password is required 则说明任务不适合直接放进无人值守流程。不要把 sudo 密码交给提示词,也不要为了省事配置覆盖全部命令的 NOPASSWD。
其他常见情况包括目标工具未安装、DNS 或代理配置错误、TLS 证书问题、systemd 用户会话不完整、CI 总体超时,以及命令本身等待网络响应。应记录失败命令和原始错误,再决定是修依赖、修环境还是调整任务边界,而不是马上用完全访问重跑。
如果上一次执行已经中断,重跑前还要检查工作树和运行状态。重复执行可能再次写入配置、重复追加内容或再次重启服务;任务说明和执行脚本都应尽量具备幂等性。
怎么证明改动真的有效,而不只是模型说“完成”?
变更前先记录基线:当前 Git 提交和工作树状态、目标配置校验结果、服务运行状态、关键指标,以及可恢复的备份或已知良好制品。变更后按“差异范围、配置语法、自动化测试、运行状态、业务健康”的顺序检查。
仓库内变更可以先看:
git status --short
git diff --check
git diff --stat
git diff -- "$TARGET"
随后运行项目已经存在的检查命令。对于 Nginx,配置语法检查和业务健康检查是两回事;nginx -t 通过并不能证明上游进程存活,也不能证明 502 已消失。在实际 Nginx 主机上,应按现有部署权限执行类似检查:
nginx -t
systemctl is-active nginx
journalctl -u nginx --since '10 minutes ago' --no-pager
还需要检查真实健康接口和错误指标。下面的地址只是示例,必须替换成环境中的实际路径:
curl -fsS http://127.0.0.1/healthz
对于 Compose 项目,应运行项目已有的配置解析命令和测试;对于 systemd 单元,应使用该系统提供的静态验证方式。不要把与当前技术栈无关的通用检查命令硬套到所有环境。
配置校验通过、服务重载成功、健康接口恢复、错误率回落,这几层证据缺一不可。“配置文件已写入”不代表进程已经加载;“服务处于 active”也不代表请求能正常返回。若验证失败,应恢复备份、上一制品或已知良好版本,并由受控流程执行回滚,而不是让模型临时再猜一个修复方案。
审计时应保存必要的 JSONL 事件、最终消息、diff、配置校验结果和健康检查结果,但要先处理其中的敏感信息。模型自述只能作为解释,不能作为变更成功的证据。
最后该把哪类任务交给 Codex?
最终选择应按风险决定,而不是按“自动化程度”决定。
| 任务类型 | 推荐方式 |
|---|---|
| 临时排障、步骤尚未确定 | 交互式 codex,从只读模式开始 |
| 定时日志检查、配置巡检 | codex exec + read-only + 外部状态检查 |
| Git 仓库内的代码或配置修改 | codex exec + workspace-write + diff/测试门禁 |
| CI 中无人值守执行 | 受限沙箱 + never,失败时阻断流水线 |
| 修改系统目录或直接操作生产服务 | Codex 生成补丁或制品,由受控部署流程应用 |
重复执行的任务应写清期望状态、允许范围、禁止动作、验证命令和停止条件。例如:
目标状态:明确说明要达到的状态。
允许范围:明确允许读取和写入的路径。
禁止动作:修改范围外文件、使用 sudo、重启服务等。
验证命令:列出仓库已有的检查方式。
停止条件:检查失败或证据不足时立即停止,不扩大权限。
期望输出:说明结论、证据和下一步检查。
这样即使任务中断,也能判断已经完成了什么、还缺什么,而不是简单再执行一遍。
下一步:先用低风险故障场景跑通
先选一个可回滚、不会影响生产流量的故障场景,用专用 Linux 用户运行只读任务,保存事件输出、最终消息和现场基线。确认它能正确引用证据且没有写文件后,再在独立分支或 worktree 中逐步开放 workspace-write,同时加入目标文件限制、diff 检查、项目测试和停止条件。
完整跑通一次人工复核流程后,再考虑定时执行或接入 CI。生产系统目录、服务重启和正式发布,继续由已有部署流程处理;不要因为 codex exec 能执行命令,就把最后的权限门禁也交给它。













暂无评论内容