
OpenResearch orx 的 SSH 计算后端实战在自有服务器上以快照方式运行实验的完整指南【免费下载链接】OpenResearchTurn your coding agents into research agents项目地址: https://gitcode.com/GitHub_Trending/op/OpenResearch导读在 OpenResearchorx的计算体系中SSH 后端--backend ssh是把你自己的机器或服务器变成实验运行节点的标准方式它不依赖任何调度器或云平台只需一个~/.ssh/config别名就能把已提交的实验快照流式传输到远程主机并以脱离终端的方式后台运行。读完本文你将掌握 SSH 后端的适用场景、一条命令的启动方式、远程运行目录的结构、快照上传与进程监督的底层原理以及取消、等待与资源选择等配套操作可以直接在自己的 GPU 服务器上跑通完整的 orx 实验流程。一、SSH 后端是什么、什么时候该用它根据 SSH 后端参考文档 的定义这个后端只应该在两种情况下被启用用户明确要求在自己的机器或服务器上运行SSH 被配置为 orx 的默认后端session playbook 中声明的 configured default。它做的事情是在一个来自~/.ssh/config的主机上以该主机的环境运行一个脱离终端detached的进程。典型命令如下orx exp run expId --backend ssh --host my-gpu-box在 orx 的计算抽象中后端backend是提交实验运行的位置计算技能说明 列出了全部九个后端Hugging Face Jobs、Modal、Kubernetes、SSH、Slurm、Ray Jobs、OpenResearch、Tinker 以及本机local。SSH 是其中唯一没有硬件调度器的后端——目标就是一台你能ssh进去的普通服务器见 src/jobs/ssh.rs 的文件头注释。判断原则只有在用户点名要用某个后端时才切换已连接的凭据本身不是切换的信号。默认情况下一律使用orx exp run expId裸命令。二、快速开始一条命令启动远端实验启动一次 SSH 后端运行的完整命令格式为orx exp run expId --backend ssh --host my-gpu-box其中expId是要运行实验的 ID--host my-gpu-box每次启动都必须提供且必须是一个 SSH config 别名不是 IP、不是userhost字符串必须是~/.ssh/config中定义的 Host 名称SSH 后端没有 flavor无机型规格概念因为机器是地址不是形状。如果漏传--host提交会在校验阶段直接报错。从源码 src/local/ssh.rs 的submit_local_ssh_with_source可以看到完整的校验逻辑if args.flavor.is_some() { return Err(anyhow!( --backend ssh has no flavors — a machine is an address, not a shape. \ Pass --host alias (an ~/.ssh/config alias). )); } if args.image.is_some() { return Err(anyhow!( --image doesnt apply to --backend ssh — the run uses the hosts own environment. )); }这段代码还揭示了一个重要的使用边界SSH 后端没有镜像image概念远程直接使用主机的原生环境因此你需要在目标主机上自行准备好 Python、依赖和运行脚本所需的一切。同样没有 timeout 标志——超时控制由orx supervise在本地侧以轮询方式体现而不是在远端强杀。启动成功后orx exp run会输出类似下面的摘要来自 launch_local_ssh 的打印逻辑✓ SSH job started. host my-gpu-box (.orx/runs/runId) run runId注意orx exp run只是入队并立即返回queues the run and returns immediately真正的监督由后台进程完成。提交后应紧跟orx runs、orx logs、orx exp wait或orx exp wake来跟踪状态。三、前提条件认证、主机工具与网络要求SSH 后端对认证的处理原则是orx 调用 ssh 客户端但永远不会读取你的私钥。认证完全交给你的 SSH 密钥或 ssh-agent以及~/.ssh/config中为别名配置的 HostName / User / IdentityFile / Port 等远程主机必须装有bash和tar因为快照上传与运行都依赖这两个工具orx 在设置界面提供了preflight检查通过command -v bash与command -v tar探测这两个工具是否就绪缺失时会提示This host needs bash and tar installed before orx can copy and run experiments实现见 src/jobs/ssh.rs 的preflight函数。关键 SSH 选项BatchMode 与 ConnectTimeout每次调用 ssh 时orx 都会附加一组共享选项见ssh_opts-o BatchModeyes # 后台批处理绝不交互式提示密码/确认 -o ConnectTimeout10 # 连接超时 10 秒其中BatchModeyes意味着后台轮询时不会弹出任何交互提示因此目标主机必须能通过密钥或 agent 无密码登录而交互式登录如设置面板里的连接测试则使用BatchModeno允许正常提示。四、远程运行目录~/.orx/runs/runId/每次运行在远端都有自己私有的、权限为700的运行目录路径为~/.orx/runs/runId/目录内由run_job和inspect_job共同维护四个关键文件见 src/jobs/ssh.rs 文件头文件作用run.sh启动器脚本导出环境变量 快照解压 运行命令snapshot-and-run payloadlog合并的 stdout/stderr 输出日志轮询读取的对象pid脱离终端进程组 leader 的 PIDexit_codepayload 结束时写入的退出码这套目录设计是整个监督模型的句柄重启后的orx supervise仅凭这个目录就能重新挂接reattach到运行上与客户端进程生死无关。run.sh的实际内容由run_job拼装src/jobs/ssh.rs#!/usr/bin/env bash export VAR1... # 已同步环境变量 HF_TOKEN 等 cd $HOME/dir || exit 97 ( # snapshot-and-run payloadset -eo pipefail; cd repo; run command ) log 21 echo $? exit_code注意 payload 被放在子 shell( … )中执行而不是{ … }分组——这样即使内部exit或set -e失败也只终止子 shell外层仍能执行echo $? exit_code从而保证退出码总被记录。五、快照如何传输一次上传、内容寻址缓存orx 的实验遵循**不可变快照immutable snapshot**原则每次运行执行的是实验分支已记录 commit 的源码快照未提交文件被排除且所有后端都不需要 GitHub push。SSH 后端使用stage_source完成快照传输src/jobs/ssh.rs本地将记录 commit 的源码打成一个 tar 归档digest 作为内容寻址标识远端先检查缓存~/.orx/source/digest.tar是否存在test -f若不存在通过 ssh 的 stdin 管道以umask 077上传到临时文件再mv原子落盘随后mkdir -p ~/.orx/runs/runId/repo并将 tar 解压到该目录作为运行的工作区。内容寻址的好处是同一 commit 的多次运行如同一实验的重跑只上传一次后续直接复用远端缓存而且上传和解压都是可重复操作客户端或 supervisor 重启后重试不会破坏状态。stage_source中上传的命令值得注意——它全程通过 ssh stdin 流式写入而不经过 scp/sftpumask 077; mkdir -p $HOME/.orx/source; \ tmp$HOME/cache.tmp.$$; cat $tmp mv $tmp $HOME/cache而远端运行的真实命令由staged_script生成src/compute.rsset -eo pipefail; cd repo; run command它保证解压失败立即中止随后cd repo进入快照工作区最后执行你在实验基线baseline上固定的运行命令。六、进程如何启动setsid 脱离终端、进程组可取消run_job的启动逻辑src/jobs/ssh.rs保证了脱离 ssh 通道关闭而存活cd $HOME/dir \ if command -v setsid /dev/null 21; then setsid bash run.sh /dev/null /dev/null 21 \ else nohup bash run.sh /dev/null /dev/null 21 fi; \ echo $! pid优先使用setsid它创建新会话使pid pgid这样取消时可以用kill -TERM -pid一次终止整个进程组目标主机没有setsid例如 macOS 主机时回退到nohup此时只能按单个 PID 终止PID 记录到pid文件供状态检查和取消使用。取消语义cancel_job因此是p$(cat $HOME/dir/pid 2/dev/null); \ [ -n $p ] { kill -TERM -$p 2/dev/null || kill -TERM $p 2/dev/null; }; true先尝试向负 PID整个进程组发送 TERM失败则退回单进程 TERM。这与参考文档中Cancellation terminates the remote process group的表述一致。七、监督与状态机orx supervise如何轮询远端启动后orx 会派生一个脱离终端的orx supervise进程在本地持续轮询远端。参考文档特别提醒不要杀掉它。它的行为在 src/commands/supervise.rs 中实现核心是两个并发任务状态轮询每 5 秒调用一次inspect_jobPOLL_INTERVAL 5s根据远端文件推断阶段exit_code存在 → 已结束0为COMPLETED非零为ERROR附退出码原因pid存在且kill -0存活 →RUNNINGpid存在但已死且无exit_code→DEAD被强杀尚无pid→PENDING刚刚启动。日志跟踪stream_logs每次用tail -n skip1 ~/.orx/runs/runId/log拉取增量日志按一行日志 一条记录的契约交给日志 sink 写入本地log_path(run_id)LOG_IDLE 30s表示日志静默多久后重新检查作业状态。因为监督状态全部落在本地 store 与远端目录backend 自身所以orx supervise是重启幂等的无论客户端、supervisor 重启多少次重新运行都能从断点继续日志去重基于已消费的行号。本地 store 中保存的后端描述符BackendDescriptor将 kind 记录为ssh_jobnamespace存主机别名job_id存远端运行目录~/.orx/runs/runId并在重启后由ssh_ref()解出(host, dir)句柄重新挂接见 src/jobs/mod.rs。等待运行完成orx exp waitorx exp wait expId # 等待该实验最近一次运行 orx exp wait --project projectId # 任一项目运行完成即返回预算循环原语 orx exp wait expId --interval 10 --timeout 3600默认轮询间隔 5 秒、默认超时 1800 秒超时以非零退出码结束含义是还没有变化而非运行失败失败运行会带reason:行启动后才失败的情况需要orx logs runId排查不想阻塞当前回合时改用orx exp wake expId它只在done或failed时触发并排队在用户消息之后wait 与 wake 二选一。八、主机密钥策略与连接复用安全细节HostKeyPolicy 三种策略orx 对远端主机密钥的处理有三种策略src/jobs/ssh.rs 的HostKeyPolicy由SshTarget::host_port统一生成对应的-o参数策略参数适用场景UserConfig不附加任何 host-key 选项用户自己敲的主机名可能已在known_hosts固定过完全交给用户配置AcceptNewStrictHostKeyCheckingaccept-new首次见到的裸 IP真正的 TOFUtrust-on-first-use首次连接接受并记录后续密钥变更会被发现EphemeralStrictHostKeyCheckingnoUserKnownHostsFile/dev/nullLogLevelERROR仅用于云平台临时供应的机器如 OpenResearch box其host:port会被平台回收复用真正的固定反而会引发虚假的不匹配alias目标即本后端场景不附加任何额外选项完全由~/.ssh/config和用户自己的known_hosts决定。ControlMaster 连接复用在 Unix 上orx 会为每个目标启用 SSH 连接复用-o ControlMasterauto -o ControlPath/tmp/orx-ssh-uid-hash/16位hex -o ControlPersist600这意味着状态轮询、日志拉取、上传等大量短连接共享同一条已认证的 TCP 会话而不是每次握手一次。ControlPath 由dest extra_opts哈希生成所以同主机不同端口不会共享 socket有专门测试control_path_differs_per_port验证路径放在/tmp下并以700权限创建是为了绕开 macOS 104 字节的 Unix socket 路径上限见control_path_fits_macos_unix_socket_limit测试。在 Windows 上Win32-OpenSSH 不支持连接复用因此显式传入ControlMasterno与ControlPathnone显式关闭而非省略防止用户自己的 ssh_config 重新启用一个导致getsockname failed的 ControlPath这也意味着 Windows 上后台调用需要 agent 密钥或无口令密钥。九、与其他后端的关联OpenResearch 与 Slurm 复用同一套 SSH 通道SSH 后端的实现并不孤单ssh_run、SshTarget等基础设施被另外两个后端复用Slurm 后端以同样的方式驱动集群登录节点login nodeOpenResearch 后端在云平台临时供应的机器上运行实验使用HostKeyPolicy::Ephemeral策略接受任意主机密钥并把ssh_host/ssh_port/ssh_user记录在后端描述符中见 src/jobs/mod.rs 的openresearch_ssh_target。两者的监督循环都走同一个watch_ssh_job运行目录在某台可 ssh 的机器上这一通用模型这也是为什么 SSH 后端自身的实现如此精简。十、配套实践计算规模选择与运行纪律配合 orx-compute 技能说明 的通用规范使用 SSH 后端时应遵循以下纪律一切运行都通过orx exp run启动绝不直接调用 ssh、调度器或训练命令本身。工作区只用于编辑、Git 与轻量检查直接作业不在记录 commit 之内可能运行与记录快照不一致的代码。保持运行命令固定fixed run command在基线上用orx project edit projectId --run-command cmd设定一次之后通过子分支改代码/配置而不是改命令。先 commit 再启动每个后端都运行记录 commit 的不可变快照未提交文件不会进入运行。计算规模先决定 GPU 还是 CPUAPI 驱动评估与数据准备通常 CPU 更划算选择能装下模型与最小 batch 的最小规格遇到真实 OOM 或慢到无望再升级而不是一开始就用最大的加速器timeout 只为真正长时间运行而调大。并发控制默认情况下同一节点已有 in-flight 运行时 orx 会拒绝再次启动确需并发时显式加--force。十一、参考路径速查后端参考文档agent-skills/orx-compute/references/ssh.md计算技能总览通用启动契约、wait/wake、规模选择agent-skills/orx-compute/SKILL.mdSSH 后端核心实现目标解析、上传、启动、监督、取消src/jobs/ssh.rs本地提交入口与校验无 flavor、无 image、必须 --hostsrc/local/ssh.rs后端描述符与ssh_ref挂接句柄src/jobs/mod.rs监督进程与 SSH 轮询循环src/commands/supervise.rs快照脚本snapshot / staged / gated生成src/compute.rs结语SSH 后端是 orx 计算抽象中最朴素却最灵活的一环没有镜像、没有调度器、没有机型只有一条指向~/.ssh/config别名的连接、一套~/.orx/runs/runId/目录约定以及orx supervise的远程轮询。理解它的文件级状态机run.sh/log/pid/exit_code、内容寻址快照缓存与setsid进程组取消语义你就能在自有 GPU 服务器上稳定、可复现地跑出与云后端完全一致的实验体验。【免费下载链接】OpenResearchTurn your coding agents into research agents项目地址: https://gitcode.com/GitHub_Trending/op/OpenResearch创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考