← Sandbox SDK / sandbox / guides
Запуск фоновых процессов
В этом руководстве показано, как запускать долго выполняющиеся фоновые процессы в песочнице, отслеживать их и управлять ими.
Когда использовать фоновые процессы
Используйте startProcess() вместо exec() когда:
- Запуск веб-серверов - HTTP-серверы, API, WebSocket-серверы
- Долго работающие сервисы - Серверы баз данных, кеши, очереди сообщений
- Серверы разработки - Серверы разработки с hot reload, режимы отслеживания изменений
- Непрерывный мониторинг - Наблюдатели за логами, проверки состояния
- Параллельное выполнение - Одновременная работа нескольких сервисов
Запустите фоновый процесс
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
// Start a web server
const server = await sandbox.startProcess("python -m http.server 8000");
console.log("Server started");
console.log("Process ID:", server.id);
console.log("PID:", server.pid);
console.log("Status:", server.status); // 'running'
// Process runs in background - your code continuesimport { getSandbox } from '@cloudflare/sandbox';
const sandbox = getSandbox(env.Sandbox, 'my-sandbox');
// Start a web server
const server = await sandbox.startProcess('python -m http.server 8000');
console.log('Server started');
console.log('Process ID:', server.id);
console.log('PID:', server.pid);
console.log('Status:', server.status); // 'running'
// Process runs in background - your code continuesНастройте окружение процесса
Задайте рабочую директорию и переменные окружения:
const process = await sandbox.startProcess("node server.js", {
cwd: "/workspace/api",
env: {
NODE_ENV: "production",
PORT: "8080",
API_KEY: env.API_KEY,
DATABASE_URL: env.DATABASE_URL,
},
});
console.log("API server started");const process = await sandbox.startProcess('node server.js', {
cwd: '/workspace/api',
env: {
NODE_ENV: 'production',
PORT: '8080',
API_KEY: env.API_KEY,
DATABASE_URL: env.DATABASE_URL
}
});
console.log('API server started');Мониторинг статуса процесса
Просмотр и проверка выполняющихся процессов:
const processes = await sandbox.listProcesses();
console.log(`Running ${processes.length} processes:`);
for (const proc of processes) {
console.log(`${proc.id}: ${proc.command} (${proc.status})`);
}
// Check if specific process is running
const isRunning = processes.some(
(p) => p.id === processId && p.status === "running",
);const processes = await sandbox.listProcesses();
console.log(`Running ${processes.length} processes:`);
for (const proc of processes) {
console.log(`${proc.id}: ${proc.command} (${proc.status})`);
}
// Check if specific process is running
const isRunning = processes.some(p => p.id === processId && p.status === 'running');Ожидание готовности процесса
Прежде чем продолжить, дождитесь готовности процесса:
const server = await sandbox.startProcess("node server.js");
// Wait for server to respond on port 3000
await server.waitForPort(3000);
console.log("Server is ready");const server = await sandbox.startProcess('node server.js');
// Wait for server to respond on port 3000
await server.waitForPort(3000);
console.log('Server is ready');Либо дождитесь определённых шаблонов в логах:
const server = await sandbox.startProcess("node server.js");
// Wait for log message
const result = await server.waitForLog("Server listening");
console.log("Server is ready:", result.line);const server = await sandbox.startProcess('node server.js');
// Wait for log message
const result = await server.waitForLog('Server listening');
console.log('Server is ready:', result.line);Мониторинг логов процесса
Транслируйте журналы в режиме реального времени:
import { parseSSEStream } from "@cloudflare/sandbox";
const server = await sandbox.startProcess("node server.js");
// Stream logs
const logStream = await sandbox.streamProcessLogs(server.id);
for await (const log of parseSSEStream(logStream)) {
console.log(log.data);
}import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
const server = await sandbox.startProcess('node server.js');
// Stream logs
const logStream = await sandbox.streamProcessLogs(server.id);
for await (const log of parseSSEStream<LogEvent>(logStream)) {
console.log(log.data);
}Либо получите накопленные логи:
const logs = await sandbox.getProcessLogs(server.id);
console.log("Logs:", logs);const logs = await sandbox.getProcessLogs(server.id);
console.log('Logs:', logs);Остановите процессы
Остановите фоновые процессы и их дочерние процессы:
// Stop specific process (terminates entire process tree)
await sandbox.killProcess(server.id);
// Force kill if needed
await sandbox.killProcess(server.id, "SIGKILL");
// Stop all processes
await sandbox.killAllProcesses();// Stop specific process (terminates entire process tree)
await sandbox.killProcess(server.id);
// Force kill if needed
await sandbox.killProcess(server.id, 'SIGKILL');
// Stop all processes
await sandbox.killAllProcesses();killProcess() завершает указанный процесс и все порожденные им дочерние процессы. Это гарантирует, что процессы, работающие в фоновом режиме, не оставляют после завершения бесхозных дочерних процессов.
Например, если ваш процесс порождает несколько рабочих процессов или фоновых задач, killProcess() очистит всё дерево процессов:
// This script spawns multiple child processes
const batch = await sandbox.startProcess(
'bash -c "process1 & process2 & process3 & wait"',
);
// killProcess() terminates the bash process AND all three child processes
await sandbox.killProcess(batch.id);// This script spawns multiple child processes
const batch = await sandbox.startProcess(
'bash -c "process1 & process2 & process3 & wait"'
);
// killProcess() terminates the bash process AND all three child processes
await sandbox.killProcess(batch.id);Запуск нескольких процессов
Запускайте сервисы последовательно, дожидаясь готовности зависимостей:
// Start database first
const db = await sandbox.startProcess("redis-server");
// Wait for database to be ready
await db.waitForPort(6379, { mode: "tcp" });
// Now start API server (depends on database)
const api = await sandbox.startProcess("node api-server.js", {
env: { DATABASE_URL: "redis://localhost:6379" },
});
// Wait for API to be ready
await api.waitForPort(8080, { path: "/health" });
console.log("All services running");// Start database first
const db = await sandbox.startProcess('redis-server');
// Wait for database to be ready
await db.waitForPort(6379, { mode: 'tcp' });
// Now start API server (depends on database)
const api = await sandbox.startProcess('node api-server.js', {
env: { DATABASE_URL: 'redis://localhost:6379' }
});
// Wait for API to be ready
await api.waitForPort(8080, { path: '/health' });
console.log('All services running');Поддерживайте контейнеры активными для долго выполняющихся процессов
По умолчанию контейнеры автоматически завершают работу после 10 минут бездействия. Для длительных процессов, которые могут иметь периоды простоя (например, конвейеров CI/CD, пакетных заданий или задач мониторинга), используйте keepAlive параметр:
import { getSandbox, parseSSEStream } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";
export default {
async fetch(request, env) {
// Enable keepAlive for long-running processes
const sandbox = getSandbox(env.Sandbox, "build-job-123", {
keepAlive: true,
});
try {
// Start a long-running build process
const build = await sandbox.startProcess("npm run build:production");
// Monitor progress
const logs = await sandbox.streamProcessLogs(build.id);
// Process can run indefinitely without container shutdown
for await (const log of parseSSEStream(logs)) {
console.log(log.data);
if (log.data.includes("Build complete")) {
break;
}
}
return new Response("Build completed");
} finally {
// Important: Must explicitly destroy when done
await sandbox.destroy();
}
},
};import { getSandbox, parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
export default {
async fetch(request: Request, env: Env): Promise<Response> {
// Enable keepAlive for long-running processes
const sandbox = getSandbox(env.Sandbox, 'build-job-123', {
keepAlive: true
});
try {
// Start a long-running build process
const build = await sandbox.startProcess('npm run build:production');
// Monitor progress
const logs = await sandbox.streamProcessLogs(build.id);
// Process can run indefinitely without container shutdown
for await (const log of parseSSEStream<LogEvent>(logs)) {
console.log(log.data);
if (log.data.includes('Build complete')) {
break;
}
}
return new Response('Build completed');
} finally {
// Important: Must explicitly destroy when done
await sandbox.destroy();
}
}
};Рекомендации
- Ожидание готовности - Используйте
waitForPort()илиwaitForLog()чтобы определять, когда сервисы готовы к работе - Очистка - Всегда останавливайте процессы по завершении
- Обрабатывайте сбои - Отслеживайте логи на наличие ошибок и перезапускайте при необходимости
- Используйте try/finally - Убедитесь, что очистка выполняется даже при ошибках
- Используйте
keepAliveдля длительных задач - Предотвращает остановку контейнера во время простоя процессов
Устранение неполадок
Процесс завершается немедленно
Проверьте журналы, чтобы узнать причину:
const process = await sandbox.startProcess("node server.js");
await new Promise((resolve) => setTimeout(resolve, 1000));
const processes = await sandbox.listProcesses();
if (!processes.find((p) => p.id === process.id)) {
const logs = await sandbox.getProcessLogs(process.id);
console.error("Process exited:", logs);
}const process = await sandbox.startProcess('node server.js');
await new Promise(resolve => setTimeout(resolve, 1000));
const processes = await sandbox.listProcesses();
if (!processes.find(p => p.id === process.id)) {
const logs = await sandbox.getProcessLogs(process.id);
console.error('Process exited:', logs);
}Порт уже используется
Завершите существующие процессы перед запуском:
await sandbox.killAllProcesses();
const server = await sandbox.startProcess("node server.js");await sandbox.killAllProcesses();
const server = await sandbox.startProcess('node server.js');Дополнительные материалы
- Справочник по Commands API - Полный API управления процессами
- Настройка параметров песочницы - Настройте
keepAliveи другие параметры - API жизненного цикла - Создавайте песочницы и управляйте ими
- Справочник по Sessions API - Создавайте изолированные контексты выполнения
- Руководство по выполнению команд - Однократное выполнение команды
- Руководство по публикации сервисов - Делайте процессы доступными
- Руководство по потоковому выводу - Отслеживание вывода процесса