半夜告警响起来,值班群里最让人心里一沉的是那句"服务挂了"。人肉登机器、翻日志、一条条敲命令,折腾十分钟把故障压下去了,天亮还得补一份谁也说不清的排障记录。
现成的运维脚本库只覆盖你提前想到的场景,遇到没写过的问题照样得靠人现场发挥;而把大模型直接扔上生产机又太危险------它会写 rm -rf,也真的敢执行。
本文分享一套把 Codex CLI 改造成"能值夜班的运维智能体"的落地方案:沙箱权限做缰绳 + 只读诊断链路 + 审批与审计护栏,可直接落地。
一、Codex 进机房前:先给它套上权限缰绳
把智能体放上服务器之前,先决定它能碰到哪些东西:
- 权限三档 :
read-only只读、workspace-write仅写工作目录、danger-full-access全放开,生产机默认停在前两档。 - 信任目录 :把
/srv/ops这类排障工作目录写进配置的 projects 段,智能体在目录里改脚本不必逐条审批。 - 审批闸门 :
approval_policy设为on-request,它想执行重启、删除时会停下来问你一句。
三档权限的边界可以这样对照:
| 模式 | 可执行内容 | 可写范围 | 适用场景 |
|---|---|---|---|
| read-only | 只读命令 | 不可写 | 排查、巡检、看日志 |
| workspace-write | 常规命令 | 仅工作目录 | 生成脚本、改配置草稿 |
| danger-full-access | 任意命令 | 任意路径 | 仅限有人盯着的临时窗口 |
下面这段配置放在家目录下,给 Codex 划出可读、可写、需审批三类边界:
toml
# ~/.codex/config.toml
model = "gpt-5-codex"
approval_policy = "on-request" # 危险命令先问我
sandbox_mode = "workspace-write" # 默认只能写工作目录
sandbox_workspace_write.network_access = false
[projects."/srv/ops"]
trust_level = "trusted" # 目录内改脚本免审批
默认只读、写入受限、危险动作必审批:先画好围栏,再谈自动化。

二、让它先拿证据再说话:把值班经验写进提示词
同一个问题,提示词写法不同,跑出来的动作完全不同:
- 上下文给足:主机名、端口、日志路径、unit 名,能写死的都写死,别让模型去猜机器长什么样。
- 动作先锁死:明确"只诊断、不修复",等它把证据摆上桌,人再决定要不要动手。
- 输出定形:要求按固定表格汇报,后面的工单和日报才有得解析。
下面这条命令用只读沙箱跑一次诊断,适合接在告警脚本里:
bash
codex exec --sandbox read-only \
"机器 k8s-node-3 上 8080 端口的容器最近频繁重启。
先只做诊断:用 ss、docker ps -a、journalctl 拿证据,
禁止执行任何重启或删除操作。
最后按【证据 / 结论 / 置信度】三列输出表格,并给出下一步建议。"
先给证据边界、再给任务、最后限定动作。
两句话的差距有多大,看这组对照:
| 写法 | 实际表现 |
|---|---|
| "帮我看看服务挂了" | 漫无目的地 grep,甚至顺手重启服务 |
| "只读诊断:容器 X 频繁重启,先收集近 30 分钟 journalctl" | 结论落在日志证据上,不碰线上状态 |
先证据、后结论,先建议、后动作。
三、告警到定位:一条可重复执行的排障链路
把值班手册翻译成智能体听得懂的排障流程:
- 链路五步 :告警触发 → 只读采集 → 智能体汇总证据 → 生成处置建议 → 人工确认后执行,危险动作处必过审批闸门。
- 脚本化触发 :告警平台 Webhook 或 cron 都去调
alert-triage.sh,谁在值班都跑出同一份报告。 - 人机分工:智能体负责跑命令和写结论,人只负责拍板要不要修复。
下面这个脚本是告警进来后的第一响应,产出一份可归档的 markdown 报告:
bash
#!/usr/bin/env bash
# alert-triage.sh <主机> <端口>:告警触发后由 Webhook 或 cron 调用
set -euo pipefail
HOST="$1"; PORT="$2"; OUT="triage-$(date +%s).md"
codex exec --sandbox read-only --output-last-message "$OUT" \
"目标 ${HOST}:${PORT} 告警,依次执行只读排查:
1) ss -lntp | grep ${PORT} 确认端口归属进程
2) docker stats --no-stream 观察内存与 CPU
3) journalctl --since '-30min' 抓取报错行
用表格汇总证据,给出根因假设与下一步建议,不要执行任何修复动作。"
ls -lh "$OUT"
采集只读 → 证据入表 → 建议与动作彻底分离。

四、巡检日报交给智能体:只读操作的安全区
每天固定时间让智能体自己巡一遍机器,人只看结果:
- 专用账号:建一个只读巡检账号,把常用查看命令加进 sudo 白名单,其余一律拒绝。
- 报告落盘:让它按固定章节产出 markdown,异常项永远排在最前面。
- 定时推送:cron 每天早上八点跑一次,结果推到值班群,省掉"今天谁去巡"的争论。
巡检范围要写成清单,而不是一句话"帮我看看":
| 巡检项 | 只读命令 | 告警阈值 |
|---|---|---|
| 磁盘水位 | df -h / |
使用率 > 85% |
| 内存压力 | free -m |
可用内存 < 10% |
| 失败服务 | systemctl --failed |
条数 > 0 |
| 近期报错 | journalctl -p err --since today |
出现 OOM、 Killed 字样 |
智能体只出报告、不动线上状态,这是它能天天跑的前提。
五、危险动作的护栏:审批、回滚、审计缺一不可
智能体越能干,越要在它动手前后各留一道闸:
- 事前审批 :高危命令一律
on-request,需要 root 的动作由人在终端确认后才放行。 - 备好回滚:要求它执行变更前先输出回滚脚本,并写进同一份报告,不许"先跑起来再说"。
- 事后审计:每次会话的 jsonl 都落在本地,解析出来就能对账谁执行了什么。
下面这段脚本解析本地会话记录,把智能体执行过的命令统计成审计清单:
python
import json, pathlib
# 解析 ~/.codex/sessions 下的会话 jsonl,统计执行过的命令与失败次数
rows = []
for f in pathlib.Path.home().glob(".codex/sessions/**/*.jsonl"):
for line in f.read_text().splitlines():
try:
ev = json.loads(line)
except json.JSONDecodeError:
continue
if ev.get("type") == "command_execution":
rows.append((f.name, ev.get("command", ""), ev.get("exit_code")))
failed = sum(1 for r in rows if r[2] not in (0, None))
print(f"共 {len(rows)} 条命令,失败 {failed} 条")
for r in rows[:10]:
print(r[1][:80], "->", r[2])
审批挡在执行前、回滚脚本备在手边、审计留痕可追溯。
六、从演示到资产:把 Codex 检查塞进 CI
能跑通一次不算数,要在流水线里稳定输出才算资产:
- 退出码约定 :脚本
set -euo pipefail,检查不通过就非零退出,CI 直接红。 - 结构固定:固定表格列名与章节顺序,下游工具才敢解析。
- 失败留证:报告文件作为 artifact 传回,方便复盘而不是重跑。
这条命令可以直接放进 CI 的检查阶段,对运维手册做一致性校验:
bash
codex exec --sandbox read-only --output-last-message report.md \
"检查 /srv/ops/runbook.md:列出所有缺少回滚步骤的变更项,
只输出 markdown 表格,不要修改任何文件。"
[ -s report.md ] || { echo "报告为空,视为失败"; exit 1; }
检查失败即阻断,报告随 artifact 留存。
常见的卡点可以按这张表排查:
| 现象 | 原因 | 处理 |
|---|---|---|
codex exec 卡住等输入 |
命令被审批策略拦下 | 收紧为只读模式或加白名单 |
| 报告格式每次都变 | 提示词没约束结构 | 在提示词里写死表格列名 |
| 工作目录写不进去 | 该路径未被信任 | 在配置 projects 段标为 trusted |
| 会话记录找不到 | 版本差异导致路径变化 | 到 ~/.codex 下确认 sessions 目录 |

结语
这套链路的价值不在"AI 会敲命令",而在于把值班动作标准化:权限三档把爆炸半径框住,只读诊断链路让每次告警都产出同一份证据表,审批与审计则让智能体的每一步都可解释、可回滚。落地顺序也很清晰------先在测试机跑通配置与诊断脚本,再接巡检 cron,最后把检查塞进 CI。
运维自动化的终点从来不是无人值守,而是让人只做该人做的决策。
把缰绳先拴好,再让 Codex 去跑夜路。