跳转到内容
搜索文档

命令

最后更新 查看 MarkdownAgent 设置

在沙箱的隔离 container 环境中执行命令并管理后台进程。

方法

exec()

执行命令并返回完整结果。

const result = await sandbox.exec(command: string, options?: ExecOptions): Promise<ExecuteResponse>

参数

  • command - 要执行的命令(可包含参数)
  • options(可选):
    • stream - 启用流式回调(默认:false
    • onOutput - 实时输出回调:(stream: 'stdout' | 'stderr', data: string) => void
    • timeout - 最大执行时间(毫秒)
    • env - 此命令的环境变量:Record<string, string | undefined>
    • cwd - 此命令的工作目录
    • stdin - 传递给命令标准输入的数据(可在无 shell 注入风险的情况下传入任意输入)

返回:带有 successstdoutstderrexitCodePromise<ExecuteResponse>

const result = await sandbox.exec("npm run build");

if (result.success) {
	console.log("Build output:", result.stdout);
} else {
	console.error("Build failed:", result.stderr);
}

// With streaming
await sandbox.exec("npm install", {
	stream: true,
	onOutput: (stream, data) => console.log(`[${stream}] ${data}`),
});

// With environment variables (undefined values are skipped)
await sandbox.exec("node app.js", {
	env: {
		NODE_ENV: "production",
		PORT: "3000",
		DEBUG_MODE: undefined, // Skipped, uses container default or unset
	},
});

// Pass input via stdin (no shell injection risks)
const result = await sandbox.exec("cat", {
	stdin: "Hello, world!",
});
console.log(result.stdout); // "Hello, world!"

// Process user input safely
const userInput = "user@example.com\nsecret123";
await sandbox.exec("python process_login.py", {
	stdin: userInput,
});
const result = await sandbox.exec('npm run build');

if (result.success) {
  console.log('Build output:', result.stdout);
} else {
  console.error('Build failed:', result.stderr);
}

// With streaming
await sandbox.exec('npm install', {
  stream: true,
  onOutput: (stream, data) => console.log(`[${stream}] ${data}`)
});

// With environment variables (undefined values are skipped)
await sandbox.exec('node app.js', {
  env: {
    NODE_ENV: 'production',
    PORT: '3000',
    DEBUG_MODE: undefined // Skipped, uses container default or unset
  }
});

// Pass input via stdin (no shell injection risks)
const result = await sandbox.exec('cat', {
  stdin: 'Hello, world!'
});
console.log(result.stdout); // "Hello, world!"

// Process user input safely
const userInput = 'user@example.com\nsecret123';
await sandbox.exec('python process_login.py', {
  stdin: userInput
});

execStream()

执行命令并返回用于实时处理的 Server-Sent Events 流。

const stream = await sandbox.execStream(command: string, options?: ExecOptions): Promise<ReadableStream>

参数

  • command - 要执行的命令
  • options - 与 exec() 相同(包括 stdin 支持)

返回:发出 ExecEvent 对象(startstdoutstderrcompleteerror)的 Promise<ReadableStream>

import { parseSSEStream } from "@cloudflare/sandbox";

const stream = await sandbox.execStream("npm run build");

for await (const event of parseSSEStream(stream)) {
	switch (event.type) {
		case "stdout":
			console.log("Output:", event.data);
			break;
		case "complete":
			console.log("Exit code:", event.exitCode);
			break;
		case "error":
			console.error("Failed:", event.error);
			break;
	}
}

// Stream with stdin input
const inputStream = await sandbox.execStream(
	'python -c "import sys; print(sys.stdin.read())"',
	{
		stdin: "Data from Workers!",
	},
);

for await (const event of parseSSEStream(inputStream)) {
	if (event.type === "stdout") {
		console.log("Python received:", event.data);
	}
}
import { parseSSEStream, type ExecEvent } from '@cloudflare/sandbox';

const stream = await sandbox.execStream('npm run build');

for await (const event of parseSSEStream<ExecEvent>(stream)) {
  switch (event.type) {
    case 'stdout':
      console.log('Output:', event.data);
      break;
    case 'complete':
      console.log('Exit code:', event.exitCode);
      break;
    case 'error':
      console.error('Failed:', event.error);
      break;
  }
}

// Stream with stdin input
const inputStream = await sandbox.execStream('python -c "import sys; print(sys.stdin.read())"', {
  stdin: 'Data from Workers!'
});

for await (const event of parseSSEStream<ExecEvent>(inputStream)) {
  if (event.type === 'stdout') {
    console.log('Python received:', event.data);
  }
}

startProcess()

启动长时间运行的后台进程。

const process = await sandbox.startProcess(command: string, options?: ProcessOptions): Promise<Process>

参数

  • command - 作为后台进程启动的命令
  • options(可选):
    • cwd - 工作目录
    • env - 环境变量:Record<string, string | undefined>
    • stdin - 传递给命令标准输入的数据
    • timeout - 最大执行时间(毫秒)
    • processId - 自定义进程 ID
    • encoding - 输出编码(默认:'utf8'
    • autoCleanup - 沙箱休眠时是否清理进程

返回Promise<Process> 对象,包含:

  • id - 唯一进程标识符
  • pid - 系统进程 ID
  • command - 正在执行的命令
  • status - 当前状态('running''exited' 等)
  • kill() - 停止进程
  • getStatus() - 获取当前状态
  • getLogs() - 获取累计日志
  • waitForPort() - 等待进程监听端口
  • waitForLog() - 等待进程输出中出现模式
  • waitForExit() - 等待进程终止并返回退出码
const server = await sandbox.startProcess("python -m http.server 8000");
console.log("Started with PID:", server.pid);

// With custom environment
const app = await sandbox.startProcess("node app.js", {
	cwd: "/workspace/my-app",
	env: { NODE_ENV: "production", PORT: "3000" },
});

// Start process with stdin input (useful for interactive applications)
const interactive = await sandbox.startProcess("python interactive_app.py", {
	stdin: "initial_config\nstart_mode\n",
});
const server = await sandbox.startProcess('python -m http.server 8000');
console.log('Started with PID:', server.pid);

// With custom environment
const app = await sandbox.startProcess('node app.js', {
  cwd: '/workspace/my-app',
  env: { NODE_ENV: 'production', PORT: '3000' }
});

// Start process with stdin input (useful for interactive applications)
const interactive = await sandbox.startProcess('python interactive_app.py', {
  stdin: 'initial_config\nstart_mode\n'
});

listProcesses()

列出所有正在运行的进程。

const processes = await sandbox.listProcesses(): Promise<ProcessInfo[]>
const processes = await sandbox.listProcesses();

for (const proc of processes) {
	console.log(`${proc.id}: ${proc.command} (PID ${proc.pid})`);
}
const processes = await sandbox.listProcesses();

for (const proc of processes) {
  console.log(`${proc.id}: ${proc.command} (PID ${proc.pid})`);
}

killProcess()

终止特定进程及其所有子进程。

await sandbox.killProcess(processId: string, signal?: string): Promise<void>

参数

  • processId - 进程 ID(来自 startProcess()listProcesses()
  • signal - 要发送的信号(默认:"SIGTERM"

将信号发送到整个进程组,确保主进程及其派生的任何子进程都被终止。这可防止父进程被杀死后出现孤儿进程继续运行。

const server = await sandbox.startProcess("python -m http.server 8000");
await sandbox.killProcess(server.id);

// Example with a process that spawns children
const script = await sandbox.startProcess(
	'bash -c "sleep 10 & sleep 10 & wait"',
);
// killProcess terminates both sleep commands and the bash process
await sandbox.killProcess(script.id);
const server = await sandbox.startProcess('python -m http.server 8000');
await sandbox.killProcess(server.id);

// Example with a process that spawns children
const script = await sandbox.startProcess('bash -c "sleep 10 & sleep 10 & wait"');
// killProcess terminates both sleep commands and the bash process
await sandbox.killProcess(script.id);

killAllProcesses()

终止所有正在运行的进程。

await sandbox.killAllProcesses(): Promise<void>
await sandbox.killAllProcesses();
await sandbox.killAllProcesses();

streamProcessLogs()

实时流式传输正在运行进程的日志。

const stream = await sandbox.streamProcessLogs(processId: string): Promise<ReadableStream>

参数

  • processId - 进程 ID

返回:发出 LogEvent 对象的 Promise<ReadableStream>

import { parseSSEStream } from "@cloudflare/sandbox";

const server = await sandbox.startProcess("node server.js");
const logStream = await sandbox.streamProcessLogs(server.id);

for await (const log of parseSSEStream(logStream)) {
	console.log(`[${log.timestamp}] ${log.data}`);

	if (log.data.includes("Server started")) break;
}
import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';

const server = await sandbox.startProcess('node server.js');
const logStream = await sandbox.streamProcessLogs(server.id);

for await (const log of parseSSEStream<LogEvent>(logStream)) {
  console.log(`[${log.timestamp}] ${log.data}`);

  if (log.data.includes('Server started')) break;
}

getProcessLogs()

获取进程的累计日志。

const logs = await sandbox.getProcessLogs(processId: string): Promise<string>

参数

  • processId - 进程 ID

返回:包含所有累计输出的 Promise<string>

const server = await sandbox.startProcess("node server.js");
await new Promise((resolve) => setTimeout(resolve, 5000));

const logs = await sandbox.getProcessLogs(server.id);
console.log("Server logs:", logs);
const server = await sandbox.startProcess('node server.js');
await new Promise(resolve => setTimeout(resolve, 5000));

const logs = await sandbox.getProcessLogs(server.id);
console.log('Server logs:', logs);

标准输入 (stdin)

所有命令执行方法都支持通过 stdin 选项向命令的标准输入传递数据。这可以在无 shell 注入风险的情况下安全处理用户输入。

stdin 工作原理

当你提供 stdin 选项时:

  1. 输入数据会写入 container 内的临时文件
  2. 命令通过其标准输入流接收这些数据
  3. 执行后自动清理临时文件

此方法可防止将用户数据直接嵌入命令时可能发生的 shell 注入攻击。

// Safe: User input goes through stdin, not shell parsing
const userInput = "user@domain.com; rm -rf /";
const result = await sandbox.exec("python validate_email.py", {
	stdin: userInput,
});

// Instead of unsafe: `python validate_email.py "${userInput}"`
// which could execute the embedded `rm -rf /` command
// Safe: User input goes through stdin, not shell parsing
const userInput = 'user@domain.com; rm -rf /';
const result = await sandbox.exec('python validate_email.py', {
  stdin: userInput
});

// Instead of unsafe: `python validate_email.py "${userInput}"`
// which could execute the embedded `rm -rf /` command

常见模式

处理表单数据:

const formData = JSON.stringify({
	username: "john_doe",
	email: "john@example.com",
});

const result = await sandbox.exec("python process_form.py", {
	stdin: formData,
});
const formData = JSON.stringify({
  username: 'john_doe',
  email: 'john@example.com'
});

const result = await sandbox.exec('python process_form.py', {
  stdin: formData
});

交互式命令行工具:

// Simulate user responses to prompts
const responses = "yes\nmy-app\n1.0.0\n";
const result = await sandbox.exec("npm init", {
	stdin: responses,
});
// Simulate user responses to prompts
const responses = 'yes\nmy-app\n1.0.0\n';
const result = await sandbox.exec('npm init', {
  stdin: responses
});

数据转换:

const csvData = "name,age,city\nJohn,30,NYC\nJane,25,LA";
const result = await sandbox.exec("python csv_processor.py", {
	stdin: csvData,
});

console.log("Processed data:", result.stdout);
const csvData = 'name,age,city\nJohn,30,NYC\nJane,25,LA';
const result = await sandbox.exec('python csv_processor.py', {
  stdin: csvData
});

console.log('Processed data:', result.stdout);

进程就绪方法

startProcess() 返回的 Process 对象包含用于等待进程就绪后再继续的方法。

process.waitForPort()

等待进程监听端口。

await process.waitForPort(port: number, options?: WaitForPortOptions): Promise<void>

参数

  • port - 要检查的端口号
  • options(可选):
    • mode - 检查模式:'http'(默认)或 'tcp'
    • timeout - 最大等待时间(毫秒)
    • interval - 检查间隔(毫秒,默认:100
    • path - 要检查的 HTTP 路径(默认:'/',仅 HTTP 模式)
    • status - 期望的 HTTP 状态范围(默认:{ min: 200, max: 399 },仅 HTTP 模式)

**HTTP 模式(默认)**发起 HTTP GET 请求并检查响应状态:

const server = await sandbox.startProcess("node server.js");

// Wait for server to be ready (HTTP mode)
await server.waitForPort(3000);

// Check specific endpoint and status
await server.waitForPort(8080, {
	path: "/health",
	status: { min: 200, max: 299 },
	timeout: 30000,
});
const server = await sandbox.startProcess('node server.js');

// Wait for server to be ready (HTTP mode)
await server.waitForPort(3000);

// Check specific endpoint and status
await server.waitForPort(8080, {
  path: '/health',
  status: { min: 200, max: 299 },
  timeout: 30000
});

TCP 模式检查端口是否接受连接:

const db = await sandbox.startProcess("redis-server");

// Wait for database to accept connections
await db.waitForPort(6379, {
	mode: "tcp",
	timeout: 10000,
});
const db = await sandbox.startProcess('redis-server');

// Wait for database to accept connections
await db.waitForPort(6379, {
  mode: 'tcp',
  timeout: 10000
});

抛出

  • ProcessReadyTimeoutError - 若端口在超时内未就绪
  • ProcessExitedBeforeReadyError - 若进程在就绪前退出

process.waitForLog()

等待进程输出中出现某个模式。

const result = await process.waitForLog(pattern: string | RegExp, timeout?: number): Promise<WaitForLogResult>

参数

  • pattern - 在 stdout/stderr 中匹配的字符串或 RegExp
  • timeout - 最大等待时间(毫秒,可选)

返回Promise<WaitForLogResult>,包含:

  • line - 匹配的输出行
  • matches - 捕获组数组(用于 RegExp 模式)
const server = await sandbox.startProcess("node server.js");

// Wait for string pattern
const result = await server.waitForLog("Server listening");
console.log("Ready:", result.line);

// Wait for RegExp with capture groups
const result = await server.waitForLog(/Server listening on port (\d+)/);
console.log("Port:", result.matches[1]); // Extracted port number

// With timeout
await server.waitForLog("Ready", 30000);
const server = await sandbox.startProcess('node server.js');

// Wait for string pattern
const result = await server.waitForLog('Server listening');
console.log('Ready:', result.line);

// Wait for RegExp with capture groups
const result = await server.waitForLog(/Server listening on port (\d+)/);
console.log('Port:', result.matches[1]); // Extracted port number

// With timeout
await server.waitForLog('Ready', 30000);

抛出

  • ProcessReadyTimeoutError - 若在超时内未找到模式
  • ProcessExitedBeforeReadyError - 若进程在模式出现前退出

process.waitForExit()

等待进程终止并返回退出码。

const result = await process.waitForExit(timeout?: number): Promise<WaitForExitResult>

参数

  • timeout - 最大等待时间(毫秒,可选)

返回Promise<WaitForExitResult>,包含:

  • exitCode - 进程退出码
const build = await sandbox.startProcess("npm run build");

// Wait for build to complete
const result = await build.waitForExit();
console.log("Build finished with exit code:", result.exitCode);

// With timeout
const result = await build.waitForExit(60000); // 60 second timeout
const build = await sandbox.startProcess('npm run build');

// Wait for build to complete
const result = await build.waitForExit();
console.log('Build finished with exit code:', result.exitCode);

// With timeout
const result = await build.waitForExit(60000); // 60 second timeout

抛出

  • ProcessReadyTimeoutError - 若进程在超时内未退出

相关资源

这篇文档对您有帮助吗?