−25%

cho Windows trả theo năm, đến 31/10. Xem các gói

EQVPS
Bắt đầu

SDK TypeScript cho sandbox trong 5 phút: từ npm i @eqvps/sdk đến lần chạy đầu tiên

Cài @eqvps/sdk, khởi động sandbox Firecracker từ Node.js, Deno hoặc Bun, chạy code Python, Node và shell trong đó, chuyển file và theo dõi tác vụ dài theo thời gian thực. Sáu bước với từng dòng code.

Hướng dẫn này chạy sandbox từ JavaScript hoặc TypeScript. Bạn sẽ khởi động một microVM Firecracker cô lập, chạy code bằng ba ngôn ngữ, chuyển file và theo dõi đầu ra của một tác vụ dài. Mỗi bước là một đoạn code ngắn.

Bạn cần Node.js 18+ (hoặc Deno, hoặc Bun) và một tài khoản EQVPS.

1. Lấy token

SDK xác thực bằng một token tài khoản thông thường. Trang kết nối tài khoản chỉ cách lấy token từ bảng điều khiển, API hoặc máy chủ MCP.

export EQVPS_API_KEY="your-token"

Tài khoản mới chưa có số dư sẽ nhận $1 tín dụng sandbox khi lần đầu tạo sandbox. Chừng đó đủ cho hướng dẫn này nhiều lần.

2. Cài SDK

npm i @eqvps/sdk

Các ví dụ dùng module ES và await ở cấp cao nhất. Lưu chúng thành file .mjs, hoặc .ts rồi chạy bằng npx tsx.

3. Khởi động sandbox và chạy code

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);
});

Đầu ra là id của sandbox (sb_ và thêm 24 ký tự), rồi đến 0 3.12.x. Sandbox.with xóa sandbox khi callback kết thúc, kể cả khi nó ném lỗi.

Ngôn ngữ mặc định là Python. Hai ngôn ngữ còn lại chỉ cách một tùy chọn:

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);
});

Script bị lỗi không ném ra gì cả. Hãy kiểm tra r.ok, giá trị này là true khi exit_code bằng 0 và lệnh không bị quá thời gian chờ.

4. Lệnh shell và gói

exec nhận một chuỗi shell hoặc một mảng argv. Sandbox có truy cập internet, nên cài đặt bằng npm và pip đều chạy được:

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);
});

Một lệnh gọi đồng bộ kéo dài tối đa 55 giây. Mọi thứ lâu hơn đưa vào tác vụ nền (bước 6).

5. File

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 nhận một chuỗi hoặc Uint8Array. download trả về Uint8Array, downloadText trả về chuỗi. Mỗi lần truyền giới hạn 5 MB.

6. Tác vụ dài với đầu ra trực tiếp

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
});

Tác vụ trả về ngay và không có giới hạn 55 giây. Mặc định wait kiểm tra mỗi 2 giây (pollIntervalMs thay đổi điều này). task.kill() dừng tác vụ; sb.task(id) kết nối lại từ một tiến trình khác.

Lỗi

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;
}

SDK tự thử lại 429 và 503 tối đa ba lần khi máy chủ gửi Retry-After. Lỗi 429 phổ biến nhất xuất hiện khi chạy hơn hai lệnh cùng lúc trên một tài khoản. Mọi lớp lỗi có trong tài liệu tham khảo SDK.

Chi phí của hướng dẫn này

Mỗi ví dụ sống vài giây và bị tính mức tối thiểu 60 giây: $0.00055 trên small, $0.0011 trên standard. Tác vụ ở bước 6 chạy khoảng 100 giây trên standard, tầm $0.002. Tất cả cộng lại vẫn thấp hơn nhiều so với một cent. Bảng giá đầy đủ có trong giới hạn và tính phí sandbox.

Bước tiếp theo

FAQ

@eqvps/sdk hỗ trợ những môi trường nào?

Node.js 18 trở lên, Deno và Bun. SDK không có phụ thuộc và dùng fetch có sẵn, nên cũng chạy trong trình duyệt, nhưng đừng đặt token tài khoản của bạn vào code frontend.

Sandbox có chạy được Python nếu ứng dụng của tôi viết bằng TypeScript không?

Có. Ngôn ngữ của ứng dụng và ngôn ngữ của code trong sandbox độc lập với nhau. run nhận language là python, node hoặc bash, còn exec chạy bất kỳ lệnh shell nào.

Làm sao chắc chắn sandbox sẽ bị xóa?

Dùng Sandbox.with(options, fn), hàm này xóa sandbox khi fn kết thúc hoặc ném lỗi. Với TypeScript 5.2 trở lên, bạn cũng có thể viết await using sb = await Sandbox.create().

run trả về gì khi code bị lỗi?

Một ExecResult có exit_code khác 0 và lỗi trong stderr. Không có gì bị ném ra. Exception chỉ dành cho lỗi API, như token không hợp lệ hoặc số dư trống.

Bình luận

Chưa có bình luận nào. Hãy là người đầu tiên.

Để lại bình luận

Bình luận được kiểm duyệt trước khi hiển thị.