本教程从 JavaScript 或 TypeScript 中运行一个沙箱。你会启动一台隔离的 Firecracker 微虚拟机,用三种语言运行代码、传输文件,并查看长任务的输出。每一步都是一小段代码。
你需要 Node.js 18+(或 Deno、Bun)以及一个 EQVPS 账户。
1. 获取令牌
SDK 使用普通的账户令牌进行认证。连接账户页面介绍了如何从控制面板、API 或 MCP 服务器获取令牌。
export EQVPS_API_KEY="your-token"
没有余额的新账户第一次创建沙箱时会获得 1 美元沙箱额度,足够把本教程跑很多遍。
2. 安装 SDK
npm i @eqvps/sdk
示例使用 ES 模块和顶层 await。请保存为 .mjs 文件,或保存为 .ts 并用 npx tsx 运行。
3. 启动沙箱并运行代码
import { Sandbox } from "@eqvps/sdk";
await Sandbox.with({ tariff: "small" }, async (sb) => {
console.log(sb.id);
const r = await sb.run("import platform; print(platform.python_version())");
console.log(r.exit_code, r.stdout);
});
输出是沙箱 id(sb_ 加 24 个字符),然后是 0 3.12.x。回调结束时 Sandbox.with 会删除沙箱,即使回调抛出异常也一样。
默认语言是 Python,另外两种只差一个选项:
await Sandbox.with({}, async (sb) => {
const js = await sb.run("console.log(process.version)", { language: "node" });
const sh = await sb.run("uname -r && nproc", { language: "bash" });
console.log(js.stdout, sh.stdout);
});
失败的脚本不会抛出异常。请检查 r.ok:exit_code 为 0 且命令没有超时,它才为 true。
4. shell 命令和软件包
exec 接受 shell 字符串或 argv 数组。沙箱可以访问互联网,所以 npm 和 pip 安装都能用:
await Sandbox.with({ tariff: "small" }, async (sb) => {
await sb.exec("mkdir -p /root/app && cd /root/app && npm init -y && npm i lodash", { timeout: 55 });
const r = await sb.exec(["node", "-e", "console.log(require('/root/app/node_modules/lodash').VERSION)"]);
console.log(r.stdout);
});
一次同步调用最多 55 秒,更长的任务放到后台任务里(第 6 步)。
5. 文件
await Sandbox.with({}, async (sb) => {
await sb.upload("/root/input.json", JSON.stringify({ values: [3, 5, 8] }));
await sb.run("import json; d = json.load(open('/root/input.json')); open('/root/out.txt', 'w').write(str(sum(d['values'])))");
console.log(await sb.downloadText("/root/out.txt")); // 16
});
upload 接受字符串或 Uint8Array。download 返回 Uint8Array,downloadText 返回字符串。单次传输上限 5 MB。
6. 带实时输出的长任务
await Sandbox.with({ tariff: "standard" }, async (sb) => {
const task = await sb.exec("for i in 1 2 3 4 5; do echo step $i; sleep 20; done", { background: true });
const res = await task.wait({ onOutput: (out) => process.stdout.write(out) });
console.log(res.state, res.exit_code); // done 0
});
任务会立即返回,没有 55 秒的限制。wait 默认每 2 秒轮询一次(可用 pollIntervalMs 修改)。task.kill() 停止任务;sb.task(id) 可以从另一个进程重新连接。
错误
import { Sandbox, InsufficientBalanceError, RateLimitError } from "@eqvps/sdk";
try {
await Sandbox.with({}, async (sb) => console.log((await sb.run("print(1)")).stdout));
} catch (e) {
if (e instanceof InsufficientBalanceError) console.log("Top up the balance");
else if (e instanceof RateLimitError) console.log("Busy, retry in", e.retryAfter);
else throw e;
}
服务器发送 Retry-After 时,SDK 会自动重试 429 和 503,最多 3 次。最常见的 429 来自同一账户同时运行超过两条命令。所有错误类型见 SDK 参考。
本教程的花费
每个示例只存在了几秒,按最低 60 秒计费:small 上 0.00055 美元,standard 上 0.0011 美元。第 6 步的任务在 standard 上运行约 100 秒,约 0.002 美元。全部加起来远不到 1 美分。完整价目见沙箱限制与计费。
下一步
- 同样的内容用 Python:5 分钟上手沙箱 Python SDK。
- 接入一个模型,让它运行自己写的代码:在沙箱中完成第一个智能体任务。
- 套餐和 1 美元试用:沙箱页面。
评论
暂无评论。来做第一个吧。