在新建沙箱中运行一条命令
创建一个沙箱,在其中运行命令,返回结果,然后删除沙箱。沙箱的生命周期与请求完全一致:命令结束或调用方挂断时,沙箱随之删除。命令默认最多运行 300 秒,可用 timeout_seconds 修改。无论命令运行多久,调用都会一直等待:这里不会返回 202。在响应表明命令已结束之前(JSON 响应,或事件流的 exit、error 或 end 事件),指定了 name 的沙箱已从节点的表中移除,名称也已释放:下一个调用可以立即使用同一名称。
以事件流 (text/event-stream) 返回:事件有 start、stdout、stderr、gap、exit 和 error:见事件流和终端。
所需权限范围:write 和 exec。
https://api.glac.ai/v1/run授权
请求头参数
请求体JSON必填
- startoptionalboolean
true:虚拟机启动时运行镜像自己的启动命令(ENTRYPOINT 和 CMD);false:不启动任何东西,无论镜像的标签要求什么。只要给出了(start、start_command和ready中的任何一个),就只以它为准:不读取镜像的标签sbx.start和sbx.ready。沙箱从用这些设置和env构建的模板创建(同一镜像的两种设置就是两个模板;某种设置的第一个沙箱在构建期间以starting返回),只有其所有者的沙箱会从这个模板创建。不适用于从snapshot或template创建的沙箱 (400invalid_start)。 - start_commandoptional
启动命令,以镜像的用户身份运行,其输出由沙箱的代理程序作为命令
exe-start的输出保留(最后 16 MiB,像任何命令一样用GET …/exec/exe-start和…/exec/exe-start/output读取;对于应用的实例,这也是应用日志中该实例的内容):字符串由/bin/sh -c运行,可以有多行;列表按原样运行,不经过 shell(适用于没有 shell 的镜像)。最多 1000 个参数、64 KiB,不能含 NUL 字节,第一个参数不能为空。与start: false一起给出时返回 400invalid_start。 - readyoptional
沙箱模板的虚拟机何时算作已启动:只有这项检查通过后,节点才会保存模板(使用这些设置的每个沙箱都从它克隆),这样每个沙箱中的服务从一开始就在运行。三者选一。
tcp和http由节点在宿主机上,通过预览 URL 访问沙箱所用的地址进行尝试:不需要在沙箱中运行任何东西,因此没有 shell 的镜像也能检查,但服务必须监听所有地址,而不只是 127.0.0.1。command以镜像的用户身份在沙箱中由sh运行,与标签sbx.ready一样。每 0.2 秒尝试一次,最多 120 秒;在此期间启动命令以失败结束的,等待立即结束。无论哪种情况,沙箱都会以failure_codeboot_failed失败,failure会给出检查最后得到的结果以及启动命令最后打印的内容。需要start: true或start_command(400invalid_start)。不给出时:不等待,直接保存模板。 - initoptional
沙箱的 PID 1 是什么。不给出或为 null:平台的 init,它会启动镜像的启动命令(如果有的话:
start、start_command、镜像的标签)。systemd:完整的系统。镜像自己的 systemd 作为 PID 1,节点的代理程序是它的一个服务:用户可以安装软件包、用systemctl启动服务、使用 cron 和 journal,并通过 SSH 登录,就像在一台机器上一样。创建请求指定的任何东西都不会被启动(start、start_command和ready会被拒绝,返回 400invalid_start),在 systemd 报告机器已启动后保存模板。不带image时:使用节点的完整系统镜像(--systemd-image;带 systemd 和 OpenSSH 的 Ubuntu 24.04,sandboxd/images/ubuntu),没有这种镜像的节点会拒绝,返回 400invalid_start。没有 systemd (/usr/lib/systemd/systemd) 的镜像会构建失败,failure_code为invalid_image。其模板对以同样方式请求同一镜像的任何人都可用,除非其中有调用方自己的东西(runtime、image_pull_secret)。从快照或模板创建的沙箱会被拒绝 (400invalid_start),它们沿用其虚拟机原来的样子。沙箱的其他一切功能都与任何沙箱一样:命令、文件、终端、SSH 网关、休眠和唤醒、快照和分叉、迁移、出站规则(sandboxd/README.md,「整个系统:systemd 当 PID 1」)。 - image_pull_secretoptionalstring
保存非公开镜像所在仓库凭据的机密 (
PUT /v1/secrets/{name}) 的名称:可打印 ASCII 格式的username:password,用户名到第一个冒号为止。只接受令牌的仓库会说明与令牌搭配的用户名(ECR 为AWS,Google 的为oauth2accesstoken,GHCR 任何名称均可)。节点只把凭据交给拉取镜像的工具:沙箱、其模板和节点日志中都不会有凭据的任何内容,仓库拒绝凭据时给出的说明也不含凭据(failure_code为registry_auth_failed)。沙箱从只属于其所有者的模板创建,只有指定了凭据的创建请求才会找到这个模板:不带凭据指定同一镜像时,无论节点有没有该模板,都会不登录直接向仓库请求镜像。该机密必须存在 (404secret_not_found),必须允许发往镜像所在的仓库(其allowed_hosts涵盖镜像引用中写的仓库主机,不含端口,没有指定时为docker.io;否则返回 403secret_host_not_allowed),且必须保存这样一对凭据 (400invalid_field),还必须与image一起使用(沙箱不是从镜像创建时返回 400invalid_field)。maxLength: 128 - limitsoptionalobject
创建请求所要求的规格。没有给出(或为 null)的每一项,都取节点基础模板的值,也就是不指定规格的沙箱得到的规格。最多为本节点给沙箱的上限,即
GET /internal/node的max_vcpus和max_memory_bytes(默认为宿主机的 CPU 数,最多 32,以及其内存;从不小于基础模板的规格);超出返回 400invalid_field。同一镜像的每种规格都是一个独立的模板:节点还没有用该镜像构建过某种规格时,这种规格的第一个沙箱在节点用同一镜像构建模板期间以starting返回,之后的沙箱从它克隆。不带image时,基础模板以外的规格从节点的基础镜像构建。从snapshot或template创建的沙箱沿用其规格:请求相同的规格没问题,请求其他规格返回 400invalid_field(param 为limits)。磁盘大小由节点决定:给出disk_bytes返回 400invalid_field。 - held_asleepoptionalboolean | null
true:休眠期间,发往其端口的请求不会唤醒它:预览监听器会代为返回 502
sandbox_paused,与 E2B 的代理对已暂停沙箱的响应一样 (x-preview-ingress),只有 API 调用(或它自己的定时器)才会唤醒它。它本身不会让沙箱休眠:那是POST /v1/sandboxes/{id}/sleep的事。false 或 null:与任何沙箱一样。(相当于 E2B 不带autoResume的pause,由控制平面的 E2B 兼容层设置,在其connect时移除。)default: false
Returns
200
命令已结束:以 JSON 返回结果,或返回直到结束的事件流。sandbox_id 指明所用的沙箱,它已不复存在。
string400
请求不符合本调用的要求。invalid_json:请求体不是 JSON 对象;unknown_field:请求体中有本调用不接受的字段;unknown_parameter:查询中有本调用不接受的参数;invalid_field:某个字段或查询参数类型错误或超出范围;invalid_name:name 不是有效的名称;invalid_env:env 中有环境变量无法容纳的名称或值;invalid_metadata:metadata 超出限制;expires_in_the_past:expires_at 不是将来的时间;invalid_egress:egress 不是有效的规则集:param 指明出错的部分;invalid_start:给出的 start、start_command 和 ready 不能这样搭配(有 ready 却没有启动命令,start: false 却带了 start_command),或者其中某一项与 init: "systemd" 一起给出(此时由 systemd 按其单元启动程序),或者 init: "systemd" 没有指定 image,而节点上没有完整系统的镜像 (--systemd-image),或者沙箱是从 snapshot 或 template 创建的:param 指明是哪个字段;ambiguous_source:image、snapshot 和 template 给出了不止一个;invalid_image:image 不是指向互联网上镜像仓库中某个镜像的引用;invalid_path:某个存储卷的 path 不是绝对路径,或者是 /;missing_command:缺少 command;no_such_user:user 不是沙箱中的用户;invalid_idempotency_key:Idempotency-Key 为空或超过 255 个字符。
401
missing_api_key, invalid_api_key, expired_api_key, invalid_token.
403
凭据无权执行此操作。needs_api_key:沙箱令牌不能执行此操作。spend_limit_reached:已达到支出上限。secret_host_not_allowed:机密会被发往它不允许去的主机:通过 egress.inject,或作为 image_pull_secret 发往 image 的镜像仓库(param 指明是哪一个;与 error 并列的 allowed_hosts 列出它可以去的地方)。account_share_reached:账户在本节点数据盘上占用的空间已达到单个账户的上限(见 GET /internal/node 的 drive.accounts),放不下沙箱的内存外加 1 GB 的写入空间。没有创建任何东西。
404
请求中指定的对象不存在。snapshot_not_found:快照不存在;template_not_found:模板不存在;volume_not_found:volumes 中指定的某个存储卷不存在;secret_not_found:egress.inject 中指定的机密,或 image_pull_secret 指定的机密不存在。
409
某个对象的状态不允许此操作。name_taken:名称已被占用;volume_in_use:volumes 中某个非共享存储卷属于另一个沙箱;duplicate_volume:某个存储卷在 volumes 中出现了两次;mount_path_taken:volumes 中有两个存储卷的 path 相同;too_many_volumes:volumes 中非共享存储卷的数量超过了沙箱所在机器的空余磁盘数(八个;从早于八个磁盘时期的模板或快照创建的沙箱为两个);snapshot_lost:快照的 status 为 lost;no_project_address:请求了 project_network,但节点上没有该项目的网络,或者网络中已没有空余地址;command_lost:调用等待期间命令消失了;sandbox_failed:沙箱无法启动:错误信息会说明原因(比如无法拉取镜像);idempotency_key_reused:该键已与另一个请求体一起使用过;idempotency_in_progress:使用该键的第一个请求仍在执行。checkpoints_unavailable(param 为 checkpoint):开启了 checkpoint,但本节点不支持检查点(它不把磁盘复制到对象存储,或者它的内存不分层)。
503
不可用。not_served_here:给出了 egress 规则,但本节点无法执行规则(它没有 nft);或者请求了 project_network,但本节点不把沙箱放进项目网络;或者沙箱要从节点没有模板的 image 创建,而本节点不拉取镜像(原因见 GET /internal/node 的 image_pulls;param 为 image);或者 key_missing:本节点启用了加密 (src/seal.rs),却没有所属项目的密钥或平台的密钥(错误信息会说明是哪一个):控制平面会提供密钥,之后再次发起同一调用即可 (Retry-After);或者 unavailable:volumes 中的某个存储卷没能及时挂载,稍后再次发起同一调用即可 (Retry-After):客户机没能在 60 秒内完成挂载(云盘的数据块迟迟不来:对象存储不在线,或取块程序连不上),或者这样的挂载之后它仍在从机器上卸下,或者它是逐块传来的云盘,而它的数据块暂时没有任何来源响应。
504
调用方已离开。caller_gone:调用方挂断了连接。
default
其他任何失败,格式相同。internal (500):节点出错;错误信息不会多说,节点日志中以请求的 id 记录了原因。unavailable(503,可重试):no_capacity,节点的网络槽位都已占用;memory_full,调用需要启动的虚拟机(创建、唤醒、从磁盘启动、恢复、回滚、构建)在宿主机内存中放不下(还要算上已承诺给其上运行的虚拟机的内存),也没有暂停或空闲的虚拟机可以让其休眠来腾出空间(节点的 memory);drive_full,调用需要构建模板,而节点的数据盘没有空间(节点的 drive);unavailable,节点正在关闭、沙箱 10 分钟后仍处于 starting、沙箱没有响应,或者沙箱正在迁到本节点(带 Retry-After: 1);fenced,节点的租约隔离了该沙箱 (Node.lease)。moved (409):沙箱已迁到另一个节点,由 to 指明。