从「跑完即销毁」到「用完再销毁」:云沙箱的一次进化

引言:把「执行」这件事搬走

让 AI Agent 跑一段它自己生成的代码,看输出,再决定下一步,今天已经很常见。让它跑不难,难的是让它安全地跑、干净地跑,而且下一次还能接着跑。

云沙箱就是干这个的。但真把它塞进业务流程之后你会发现,只提供一次性执行,很快就不够用了。

一、云沙箱到底在解决什么问题

云沙箱是一个按需拉起、用完即弃、与宿主机强隔离的临时执行环境。它把执行一段不受信任的代码,变成一次 HTTP 调用的事。

最常见的用法是给 AI Agent 当执行器:模型生成的代码、用户粘贴的脚本,都得在受控边界里跑,不能直接落在自己的机器上。再就是 CI 和构建测试,每次都要一个干净、可复现的环境,上一次的临时文件不能污染这一次的结果。还有一次性数据处理,文件丢进去,结果拿回来,中间过程不必留着。

四件事说起来简单,同时做到不容易:不可信代码不能逃逸,环境不复用脏状态,不为偶发的峰值长期养机器,还得能被自动化流程直接调用。

二、技术原理:一个沙箱是怎么长出来的

拆开看,云沙箱大致由四层构成。

第一层是隔离层。 沙箱本质上是在同一台宿主机上切出一块「看起来独立」的运行环境:namespace 切进程、网络和挂载视图,cgroup 限制 CPU、内存、进程数,再叠加系统调用过滤,把危险入口收窄。资源不够就拒绝请求,不会拖慢邻居。

第二层是镜像层。 镜像决定沙箱里有什么,而镜像本身就是代码入口,所以必须受控。平台目前只允许 Docker Hub 的公网镜像,其他仓库直接返回 INVALID_IMAGE。不指定镜像时用平台默认镜像,这也是冷启动最快的路径。另外注意,镜像自带的 ENTRYPOINT / CMD 不生效,执行什么完全由传入的命令决定。

第三层是生命周期层。 一个沙箱的一生是:创建 → ready → busy 执行中 → 销毁,中间夹着计时、配额、网络模式(none 彻底断网,default 走平台出网白名单)、资源规格一堆状态机。这层做得好不好,用户能感知到的只有一个指标:从发出请求到第一条输出,要等多久。

第四层是数据与可观测层。 三个容易被低估、但决定「能不能被工程信任」的细节:

  1. 交换目录。输入输出统一走 /workspace,用 .zip / .tar.gz / .tgz 压缩包传递,不把大文件塞进请求体;导出的链接可以直接作为下一次任务的输入,天然形成任务链。
  2. 流式输出。长任务的 stdout / stderr 走 SSE 增量推送,事件按 started → stdout/stderr → completed 到达,片段由客户端自己按序拼接。
  3. 结果判断。HTTP 200 只说明接口调用成功,命令成不成功要看 data.status;每个逻辑任务带一个稳定的幂等键,重试时复用原值,服务端就不会重复执行、重复计费。

计费也直白:一次性任务按「固定费用 + 已完成整分钟」,会话按存活时长,快照都在响应的 billing 里。

三、百智云云沙箱:让沙箱活到你把话说完

前面两节是通用原理。我们自己的产品叫百智云云沙箱(Huskbox) ,地址在 https:// huskbox.app.baizhi.cloud

我们把这些能力封装成一套 OpenAPI:请求用 Authorization: Bearer <token>X-API-Key 鉴权,响应统一是 code / message / data 的信封结构。调用方不用自己维护容器、调度和隔离边界,发一个 HTTP 请求就能拿到一台沙箱。

它最初只有一种形态:一次性任务。POST /executions/run 提交一条命令,连接挂着直到任务结束,返回状态、输出和工作区链接。很适合脚本和 CI,每次调用都是一个全新的、彼此无状态依赖的沙箱。

但真实的工作流往往有状态:装依赖、跑构建、再跑测试,或者 Agent 要多轮「执行 → 观察 → 修正」。每一步都重新拉沙箱的话,冷启动重复一遍,依赖重装一遍,两次执行之间还传不了任何东西。

所以我们补上了会话型沙箱。用起来三步:

bash 复制代码
# 1. 创建会话,保存返回的 data.id
POST /openapi/v1/sandboxes          # { "timeout_seconds": 600 }

# 2. 在同一个 id 上连续执行命令
POST /openapi/v1/sandboxes/:id/commands

# 3. 用完显式销毁,顺带导出整个 /workspace
DELETE /openapi/v1/sandboxes/:id

比一次性任务多出来的,主要是以下内容:

  • 连续执行。同一环境里连续跑多条命令,文件系统、已装依赖、中间产物都保留。同一时刻只允许一条命令运行,busy 时新命令会被拒绝,两条命令不会互相踩数据。
  • 两类超时是分开的。会话的 timeout_seconds 是存活窗口,跟单条命令的超时没有关系。存活窗口随时可以用 POST /sandboxes/:id/timeout 从当前时刻重算;auto_extend 让活跃会话自动续期,但不会超过 max_deadline_at 这个硬上限。
  • 状态可查。GET /sandboxes/:id 返回 readybusydestroyed 等明确状态;万一丢了 id,GET /sandboxes 能找回来,顺手清掉闲置的会话。
  • 可审计。命令历史分页返回程序名、参数个数、耗时、退出码,但不返回完整参数。要看细节再查单条命令详情,argv 里的 Token、密码和 Authorization 请求头都已经脱敏。
  • 用完销毁。DELETE 时会尽量导出整个 /workspace,返回临时下载链接。工作区太大就返回 WORKSPACE_TOO_LARGE,不销毁,删掉一些文件再试就行。

两种形态放在一起:

维度 一次性任务 会话型沙箱
生命周期 命令结束自动释放 命令结束仍存活,需显式销毁
状态保持 文件系统、依赖、产物全部保留
典型场景 脚本、CI、单次执行 多步构建、多轮 Agent 交互
超时语义 单条命令超时 存活窗口 + 单条命令超时,两层独立
计费 固定费用 + 已完成整分钟 按沙箱存活时长

最后一个容易踩的坑:命令结束,会话还在。计费继续、资源继续占着,不用了一定要 DELETE,那之后计费才停。


结语

回到开头。跑一段代码,一次性任务就够了;要一段连着一段地跑,就用会话型沙箱。两种形态共用一套接口,从单次脚本到多轮 Agent 交互都覆盖得到。

完整接口与示例在百智云控制台生成的 API 文档里,欢迎试用。

访问地址:百智云·云沙箱

相关推荐
孫治AllenSun1 小时前
【LangChain4J-09】开发学习知识点
spring boot·后端·学习
lisin-lee-cooper2 小时前
简单聊聊 Spring 框架源码
java·后端·spring
kyriewen2 小时前
AI 改祖传模块后,代码评审总绕不开两个问题
前端·程序员·ai编程
复方金银花颗粒2 小时前
reactor和proactor的好处和坏处。为什么要用reactor而不用 proactor?
后端·信号处理
IT_陈寒2 小时前
JavaScript的这个隐式转换特性差点让我加班到凌晨
前端·人工智能·后端
用户8356290780513 小时前
使用 Python 在 Excel 中添加和编辑形状
后端·python
用户204937554953 小时前
端侧语音部署踩坑:模型能跑不等于终端真的能用
后端·算法
n8n3 小时前
Spring AI 结构化输出实战:让模型返回 JSON,而非自由文本
后端