Codex 源码解析 · 第 28 讲
Codex 源码解析系列 第 28 讲:Exec Server 远程执行服务 基于 OpenAI Codex 源码 · 2026-10-22 💡 本讲一句话: Codex 把"在哪台机器上跑命令"抽象成一个 Environment——本地进程和远程 exec-server 共用同一个 ExecBackend trait;懒连接、重连合并、按 seq 排序的输出流、RAII 防僵尸会话,30K 行代码全在为这一件事服务。 一、一个 Environment,三套抽象 前几讲我们拆过 unified_exec(第 16-17 讲):core 里的进程管理器只认 ExecProcess 、 StartedExecProcess 这类接口,从不关心命令到底跑在本机还是远端。这个"不关心"能成立,靠的就是 exec-server crate(30K LOC)提供的统一门面—— Environment 。 看它的定义就明白设计意图:进程执行、文件系统、HTTP 出站三条能力,全部收敛到同一个结构体里。core 拿到一个 Environment,就等于同时拿到了"能跑命令的机器 + 能读写的文件 + 能发请求的网络"。 📄 codex-rs/exec-server/src/environment.rs (第 667-680 行) pub struct Environment { // 一个"执行环境" = 进程 + 文件系统 + HTTP,三套抽象打包在一起 remote_client: Option<LazyRemoteExecServerClient>, // 远程执行客户端;None 表示这是纯本地环境 ready_info: Arc<ArcSwapOption<EnvironmentReadyInfo>>, // 就绪信息用 ArcSwap 热替换:读方永不阻塞写方 provisioning_status_tx: Option<watch::Sender<Option<Result<(), String>>>>, // 供给进度广播通道(Pending / Ready / Failed) startup_task: Arc<Mutex<Option<AbortOnDropHandle<()>>>>, // 后台启动任务句柄:Environment 被 drop 时自动取消,防泄漏 exec_backend: Arc<dyn ExecBackend>, // 统一执行后端 trait:LocalProcess 或 RemoteProcess 二选一 filesystem: Arc<dyn ExecutorFileSystem>, // 文件系统抽象(本地 / 远程 / 沙箱化三种实现) http_client: Arc<dyn HttpClient>, // HTTP 出站通道,同样走这个环境——网络策略天然统一 local_runtime_paths: Option<ExecServerRuntimePaths>, // 本地模式下的运行时路径(shell、工具链位置) } 为什么这样设计: 注意 exec_backend 是 trait object—— LocalProcess (本机 fork)和 RemoteProcess (走 RPC 到远端 exec-server)实现同一个 ExecBackend 。core 的 unified_exec 层因此完全无感:审批、超时、输出消费逻辑写一遍,本地和远程通用。而把 filesystem 和 http_client 也塞进 Environment,是因为沙箱和网络策略必须跟着"执行位置"走——命令在哪台机器上跑,文件读写和网络访问就必须受同一套策略约束,三者拆开就会出现"命令在远端、网络却在本地放行"的策略漏洞。 二、懒连接与重连合并:LazyRemoteExecServerClient 远程执行的第一道难题是连接管理。Codex 的答案是一个"懒客户端": LazyRemoteExecServerClient 本身不持有任何连接,它持有的是 连接参数 + 三个共享槽位 (startup / current_client / reconnect)。所有调用者 clone 的都是同一个 A…
阅读全文:Codex 源码解析 第 28 讲