资讯动态

OpenRig Testbed L2 运行手册:容器内 tmux 服务端生命周期验证(detach 存活、多窗格、send-keys 与 capture 字节级回环)

发布时间:2026/9/30 6:44:30 来源:尧图企业网站定制
人工智能AI Agent多智能体Agent 编排代码智能体CLI【免费下载链接】openrigMulti-agent harness that runs Claude Code and Codex together as one system项目地址https://gitcode.com/GitHub_Trending/op/openrig点击查看免费下载OpenRig 的整个运行体系都建立在 tmux 服务端这一基座之上——多 Agent 会话、终端复用、席位交接seat-handover全部经由 tmux 完成。本文讲解仓库内 docker/testbed/runbooks/L2-tmux-server-lifecycle.md 这条 L2 验证腿它运行在宿主侧、紧接 L1 之后用三个可脚本化检查L2.1 会话在客户端 detach 后存活、L2.2 多窗格共存、L2.3 send-keys → capture-pane 字节级回环证明 testbed 容器内的 tmux 服务端行为符合产品依赖的基座语义。读完本文你将掌握这套证据定义式验证的完整命令序列、PASS/FAIL 判定标准、证据落盘与清理流程并理解它背后与 TmuxAdapter 源码、Dockerfile 镜像层的对应关系。一、L2 在 testbed 验证序列中的位置与目标openrig-testbed 的验证采用宿主执行、证据定义host-executed, evidence-defined的运行手册模式即 runbooks/README.md 所述的51-09 live-legs 模式每个 leg 都是一段脚本化检查绝不允许凭记忆断言never assert from memory——先运行、抓取真实字节、再据字节下结论。整条验证序列为L0 → build → L1 → L2 → L3 → L4 → L5L6 在 L3 之后执行。各腿的职责如下表Leg验证目标运行手册L0digest 固定的基础镜像 stub 资产清单解析构建前置条件L0-resolve-inputs.mdL1PTY 分配docker run -t tmux capture-pane 返回真实字节resize 生效L1-pty-allocation.mdL2tmux 服务端生命周期detach 存活、多窗格、send-keys capture 字节回环L2-tmux-server-lifecycle.mdL3容器内 daemonboot 本地 sqlite、healthz 端口、rig up收敛零 token stub 拓扑L3-daemon-in-container.mdL451-02 密封契约容器内 env-helper 仍拒绝外部OPENRIG_URLfail-closed 不被反正都在容器里削弱L4-hermetic-fail-closed.mdL5多主机N 个容器作为 N 个命名 self-host经 host registry 经 HTTP 组网含 51-09 live-leg riderL5-multi-host-and-51-09.mdL651-02 runner 容器模式按 manifest 身份驱动真实场景 宿主模式字节级一致 L4 fail-closed 的 step-3 形态L6-container-runner-e2e.mdL2 的口号是tmux 服务端——整个产品赖以运行的基座the substrate the whole product rides——必须在容器内表现得与宿主一致。它复用了 L1 建立的固定 80×24 视口 tmux 内验证模式该模式同样被 TUI spike 的 fixed-viewport 思路采用并把验证粒度从单会话能输出推进到服务端生命周期语义。二、Setup镜像身份、证据目录与一次性容器L2 的准备工作与前序腿保持一致三行命令完成三个要点GIT_SHA$(git rev-parse HEAD); IMAGEopenrig-testbed:${GIT_SHA}; EVIDdist/testbed-image/evidence/${GIT_SHA}; mkdir -p ${EVID} NAMEorig-l2-${GIT_SHA:0:8}; docker run -d -t --name ${NAME} ${IMAGE}要点拆解镜像身份按 manifest 绑定所有 leg 都运行在构建动词打上标签的镜像上即openrig-testbed:${GIT_SHA}等于 manifest 中的manifest.image。按 README 共享约定信任某条 leg 结果前应先用docker image inspect ${IMAGE} --format {{.Id}}交叉核对运行镜像再查看dist/testbed-image/manifest.json确认本次运行的 census 身份可比对。证据目录按 SHA 哈希EVIDdist/testbed-image/evidence/${GIT_SHA}是每次运行的证据目录。每条 leg 把抓取结果与VERDICT行写入其中之后操作者对目录整体做 sha256find . -type f -print0 | sort -z | xargs -0 sha256sum使证据防篡改、可跨镜像版本比对——这就是 census-receipt 纪律。一次性、可丢弃容器docker run -d -t以 detach 方式启动-t分配 PTYNAME前缀orig-l2标明腿身份。按 fences 约定禁止挂载真实 HOME/真实 workspace 卷-v禁用新容器 全新 HOME 是密封性底线场景文件字节不变多主机容器之间唯一共享面是 docker network。容器内为什么能跑 tmux来自 Dockerfile 层 1 的显式安装apt-get install ... tmux tini procps ...。层 5 进一步保证服务端友好环境——以非 root 用户openrig运行ENTRYPOINT为/usr/bin/tini -- /opt/openrig-testbed/entrypoint.shtini 作为 PID 1 负责回收 tmux 服务端的子进程这是 tmux-server-friendly 初始化的关键entrypoint.sh 在收到OPENRIG_SELF_HOST_ID时向 stderr 宣告 self-host 身份然后exec $承接容器命令默认sleep infinity保持容器驻留。三、L2.1 — 服务端在 detach 后存活detach-survivedocker exec ${NAME} tmux new-session -d -s l2 -x 80 -y 24 docker exec ${NAME} tmux send-keys -t l2 echo persist-marker-$$ /tmp/l2.marker Enter sleep 1 # A detached session is the default with -d; confirm the server session still list after a beat. docker exec ${NAME} tmux ls | tee ${EVID}/L2-sessions.txt docker exec ${NAME} cat /tmp/l2.marker | tee ${EVID}/L2-marker.txt语义与判定tmux new-session -d -s l2 -x 80 -y 24-d表示一开始就 detach不挂任何客户端同时显式给定 80×24 固定视口——这正是 L1/TUI-spike 的 fixed-viewport 模式。这条命令验证的不只是能建会话而是服务端在没有任何客户端附着的情况下独立存活。send-keys ... echo persist-marker-$$ /tmp/l2.marker Enter通过 send-keys 向会话投递一条 shell 命令并回车提交。$$由 pane 内的 shell 展开为进程 PID因此 marker 文件内容天然携带这个命令确实在 pane 的 shell 里执行过的证明。sleep 1后tmux ls确认服务端与会话在一拍之后仍然列得出。PASS 标准tmux ls显示l2仍然存活且 marker 文件存在FAIL 标准出现 no server running 或看不到l2。这条腿的本质是验证detach 不会杀死会话这一 tmux 服务端契约。产品侧对同一契约的依赖在 TmuxAdapter.startServer() 中有直接体现适配器用tmux -D /dev/null /dev/null 21 启动一个空的服务端无会话、无 seat随后通过probeSession轮询25ms × 20 次直到 socket 可到达其配套测试 tmux-adapter.test.ts 用 mock exec 验证了空服务端只启动一次、重复请求被调和reconcile、不额外 new-session的行为。也就是说L2.1 在容器层面证明的服务端独立于客户端存活正是产品层startServer()一切后续操作的先决条件。四、L2.2 — 多窗格共存multi-panedocker exec ${NAME} tmux split-window -t l2 -h docker exec ${NAME} tmux list-panes -t l2 -F #{pane_index} | tee ${EVID}/L2-panes.txtsplit-window -t l2 -h在会话l2内做一次水平切分产生第二个 pane。list-panes -t l2 -F #{pane_index}用格式串只输出每个 pane 的索引。PASS 标准至少出现两个 pane 索引0、1FAIL 标准只有一个 pane 或命令报错。产品侧对一个会话内多 pane 共存的使用极其频繁TmuxAdapter 用list-panes枚举窗格并解析出pane_id / pane_index / pane_current_path / pane_width / pane_height / pane_active六元组见 tmux.ts 的 PANE_FORMAT 与parsePaneLine席位seat就承载在这些 pane 上。而split-window之后的 pane 布局是rig up并行拉起多个 Agent 席位、以及多 Agent 在同一会话内协作的基础拓扑形态。五、L2.3 — send-keys capture 字节级回环exact bytesTOKENroundtrip-$(date %s 2/dev/null || echo fixed)-marker docker exec ${NAME} tmux send-keys -t l2.0 printf %s\n ${TOKEN} Enter sleep 1 docker exec ${NAME} tmux capture-pane -p -t l2.0 | tee ${EVID}/L2-roundtrip.txtTOKEN使用时间戳生成唯一标记date %s不可用如某些极简容器时回退到字面量fixed保证命令在任何环境都能生成 token。send-keys -t l2.0 ... Enter目标从会话l2精确到panel2.0第一个窗格投递一条printf命令并提交。printf %s\n ${TOKEN}的输出不含多余转义是为了让回环比对只关心字节本身。capture-pane -p -t l2.0-p以纯文本print方式抓取该 pane 当前屏幕。PASS 标准capture 结果中逐字包含${TOKEN}——精确字节经过服务端完成了一次往返FAIL 标准token 缺失或乱码garbled。字节级回环是整个验证的精髓如果 tmux 服务端在容器内存在 PTY 处理、编码、换行转换等方面的问题token 必然无法原样回收。产品侧对 capture 语义的区分值得对照阅读TmuxAdapter 提供两种抓取——capturePaneContent 使用-S -lines抓取滚动缓冲而 capturePaneScreen 使用无-S的capture-pane -p抓取当前可见屏幕live-terminal seed OPR.0.4.0.38 必须用可见屏幕因为滚动缓冲会重新引入绝对绘制要消除的行漂移。L2.3 的capture-pane -p正是可见屏幕抓取的最小形态。另外产品在投递文本时远比裸send-keys谨慎sendText走load-buffer→paste-buffer -d -r -p的缓冲粘贴路径-r保留原始 LFtmux 默认会把 LF 替换为 CR而 CR 在 Claude/Codex 的 TUI 里等于 Enter提交会导致多行内容逐行误提交、-d粘贴后丢弃缓冲、临时文件与缓冲名每次调用唯一以避免并发rig up撞名sendShellCommand甚至把整条命令写进临时脚本再让 pane 内 shell 消费。L2.3 之所以用最原始的send-keys单行命令正是要测试最底层、最朴素的路径——它通过了上层缓冲粘贴路径才值得信任。六、Teardown 与证据收尾VERDICT 的落盘判定docker rm -f ${NAME} /dev/null { grep -q l2 ${EVID}/L2-sessions.txt [ $(wc -l ${EVID}/L2-panes.txt) -ge 2 ] grep -q ${TOKEN} ${EVID}/L2-roundtrip.txt \ echo VERDICT: PASS — server survives detach, multi-pane, exact round-trip \ || echo VERDICT: FAIL — see L2-*.txt; } | tee ${EVID}/L2-verdict.txt清理docker rm -f ${NAME}强制移除一次性容器不留任何残留可丢弃容器是密封性底线的一部分。判定逻辑三个 grep/计数条件分别对应三条腿的 PASS 标准——grep -q l2 L2-sessions.txttmux ls输出中存在l2detach 存活wc -l L2-panes.txt≥ 2至少两个 pane 索引多窗格grep -q ${TOKEN} L2-roundtrip.txtcapture 中逐字出现 token字节回环。输出把VERDICT: PASS|FAIL — 一行说明写进L2-verdict.txt作为该腿的证据收尾。按 README 约定每条 leg 的证据都应记录确切命令 抓取到的字节 单行 VERDICT基于观测到的字节绝不凭记忆。之后整个dist/testbed-image/evidence/${GIT_SHA}目录会被 sha256 汇总形成可跨镜像版本比对的防篡改证据集。七、从 L2 到整个 testbed为什么必须逐字节验证L2 看似只是三条 tmux 命令但它服务于仓库里一条反复出现的纪律可观测结果绝不能凭记忆断言the clause that caught the Apple-container premise——正是这个条款抓住了Apple 容器前提的错误。README 明确要求一条腿若无法完成检查必须报告响亮的阻塞loud blocker给出确切命令与缺失能力绝不允许凭记忆绿灯通过。因此若你正在为 OpenRig 的容器化部署排障L2 是最先该跑的最小检查集——它不依赖任何业务代码、不需要 LLM、不需要 token纯靠tmux二进制 tini初始化就能定位容器内终端基座是否成立。若你是 TUI/席位功能rig up、seat-handover、live-terminal seed的开发者L2 验证的 detach-survive 与字节回环正是 TmuxAdapter 大量方法startServer/sendKeys/capturePaneScreen/respawnPane/switchClient等成立的前提配套单测 tmux-adapter.test.ts 给出了 mock exec 层面的对照实现。Fences对所有 leg 有约束力不挂载真实 HOME / 真实 workspace 卷fresh container fresh HOME 是密封性下限场景字节不改多主机容器间唯一共享面是 docker network。L2 遵守全部三条docker run无-v命令与判定逐字可复现单容器不涉及网络共享。按验证序列推进先由 L0 固定 base digest 与 stub census构建出镜像L1 证明 PTY 与真实捕获字节L2 再证明服务端生命周期与多窗格/回环语义之后 L3 才会在这个基座上启动容器内 daemon、用 stub-assets/rig.yaml 里的零 token stub 拓扑做rig up收敛验证。L2 通过才谈得上产品赖以运行的基座在容器内成立。赞分享人工智能AI Agent多智能体Agent 编排代码智能体CLI【免费下载链接】openrigMulti-agent harness that runs Claude Code and Codex together as one system项目地址https://gitcode.com/GitHub_Trending/op/openrig点击查看免费下载相关推荐Woodpecker 流水线 Services 完整指南服务容器定义、端口映射、生命周期与 detach 分离执行Woodpecker 流水线 Services 完整指南服务容器定义、端口映射、生命周期与 detach 分离执行 Woodpecker CI 在 YAMLCI/CDDevOpsKubeEdge 依赖中的 Masterminds/semver v3 解析从 CHANGELOG 到源码的语义化版本管理全解KubeEdge 依赖中的 Masterminds/semver v3 解析从 CHANGELOG 到源码的语义化版本管理全解 导读 Masterminds/人工智能AI Agent多智能体Agent 编排代码智能体CLIopenrig testbed 容器模式端到端验证L6按镜像清单身份驱动真实场景、主机模式字节级对等与失败关闭openrig testbed 容器模式端到端验证L6按镜像清单身份驱动真实场景、主机模式字节级对等与失败关闭 本指南基于 openrig 仓库 dock人工智能AI Agent多智能体Agent 编排代码智能体CLI上一篇TypeScript-React-Starter代码质量门禁在CI中强制执行代码标准下一篇如何使用readme-md-generator快速创建专业项目文档的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑