INTEGRITY Dokumentace

Procesy

Spouštějte a sledujte kontrolované procesy v aktuálním kontejneru sandboxu.

Vysvětlení principu fungování najdete v Provádění procesů. Pro interaktivní vstup PTY a terminály v prohlížeči viz Terminály a Terminals API.

Popisovače procesů mají žádný standardní vstup. Použijte cwd, env, a argv (nebo explicitní shellový skript) pro neinteraktivní práci. Použijte terminál když potřebujete interaktivní PTY.

exec()

Spusťte proces z argv (spustitelný soubor, poté argumenty). Vyřeší se ve chvíli, kdy se spuštění zdaří, nikoli až proces skončí. SDK nespouští shell a neprovádí shell escaping hodnot v argv, každý prvek představuje jeden argument procesu.

exec(command: SandboxCommand, options?: ExecOptions): Promise<SandboxProcess>

SandboxCommand

type SandboxCommand = readonly [executable: string, ...args: string[]];

ExecOptions

Pole Typ Popis
cwd string Pracovní adresář pro toto spuštění. Výchozí hodnota je /workspace když není nastavena.
env Record<string, string> Překrytí prostředí pro toto spuštění. Neovlivní pozdější spuštění. Env na úrovni sandboxu se i tak použije.
timeout number Doba života vzdáleného procesu v milisekundách. Supervisor může proces zastavit; dokončení může hlásit timedOut: true.

Vrací

Promise<SandboxProcess>

const process = await sandbox.exec(["node", "--version"]);
const output = await process.output({ encoding: "utf8" });

console.log(process.id, process.pid, output.stdout, output.exitCode);
const process = await sandbox.exec(["node", "--version"]);
const output = await process.output({ encoding: "utf8" });

console.log(process.id, process.pid, output.stdout, output.exitCode);

getProcess()

Vrátí popisovač procesu běžícího v aktuální kontejner pro tento sandbox, nebo null.

Pokud neběží žádný kontejner, nespustí nový. Vrátí null když neběží žádný kontejner, když je ID procesu v aktuálním kontejneru neznámé nebo když daný proces patřil předchozímu kontejneru se stejným ID sandboxu.

getProcess(id: string): Promise<SandboxProcess | null>

ID procesů nejsou trvalá napříč zastavením nebo nahrazením kontejneru. Viz Jak dlouho proces žije.

listProcesses()

Vypíše procesy v aktuálním kontejneru tohoto sandboxu. Pokud žádný kontejner neběží, nespustí ho. Pokud žádný kontejner neběží, vrátí prázdný seznam.

listProcesses(): Promise<ProcessStatus[]>

Každá položka je ProcessStatus hodnota (stejná struktura jako status()).

SandboxProcess

Člen Popis
id ID procesu v aktuálním kontejneru.
pid PID kontejneru při spuštění.
exitCode Promise<number> který se vyřeší, jakmile se sledovaná skupina procesů ustálí.
status() Aktuální rozlišený stav.
logs(options?) Proud logů založený na kurzoru.
output(options?) Bufferované stdout a stderr plus metadata o ukončení.
waitForExit(options?) Počkejte, až se sledovaná skupina procesů ustálí.
waitForLog(pattern, options?) Počkejte, až stdout nebo stderr odpovídá vzoru.
waitForPort(port, options?) Počkejte, až bude port připraven, nebo dokud kontrola připravenosti neselže.
kill(signal?) Odešlete číselný signál. Výchozí 15 (SIGTERM).

Toto handle nemá API pro process stdin.

status()

status(): Promise<ProcessStatus>

Viz ProcessStatus. Proces zůstává running dokud sledovaný skupina procesů se ustálí, i když kořenový pid skončí, zatímco potomci pokračují.

output()

Ukládejte stdout a stderr do bufferu, dokud proces neskončí (nebo neskončí místní čekání), a poté vraťte metadata o ukončení.

output(options?: ProcessOutputOptions): Promise<ProcessOutput<Uint8Array>>
output(
	options: ProcessOutputOptions & { encoding: "utf8" },
): Promise<ProcessOutput<string>>

ProcessOutput

interface ProcessOutput<T = Uint8Array> {
	stdout: T;
	stderr: T;
	exitCode: number;
	signal?: number;
	timedOut: boolean;
	truncated: boolean;
}

Výchozí kódování těla je binární (Uint8Array) pokud nepředáte encoding: "utf8". Upřednostněte logs() když výstup může přesáhnout to, co chcete ukládat do bufferu.

ProcessOutputOptions

Pole Typ Popis
encoding "utf8" Dekódujte stdout/stderr jako řetězce.
maxBytes number Omezte počet bufferovaných bajtů na každou stranu streamu výsledku; můžete nastavit truncated: true. Pokud je vynecháno, výchozí limit neplatí.
timeout number Pouze lokální lhůta čekání v milisekundách; proces se neukončí.
signal AbortSignal Zrušte pouze toto čekání; proces tím neukončíte.

maxBytes musí být nezáporné konečné číslo, pokud je nastaveno.

const process = await sandbox.exec(["/bin/bash", "-lc", "npm test"], {
	cwd: "/workspace/app",
});
const result = await process.output({ encoding: "utf8", timeout: 120_000 });

console.log(result.exitCode, result.stdout, result.timedOut, result.truncated);
const process = await sandbox.exec(["/bin/bash", "-lc", "npm test"], {
	cwd: "/workspace/app",
});
const result = await process.output({ encoding: "utf8", timeout: 120_000 });

console.log(result.exitCode, result.stdout, result.timedOut, result.truncated);

logs()

Streamujte přehratelné události protokolu pomocí neprůhledného kurzoru.

logs(options?: ProcessLogsOptions): Promise<ReadableStream<ProcessLogEvent>>

ProcessLogsOptions

Pole Typ Popis
since string Neprůhledný kurzor; pokračuje po předchozí události.
replay boolean Při obnovení zahrne historii uloženou ve vyrovnávací paměti.
follow boolean Udržujte stream otevřený pro živý výstup.
signal AbortSignal Zrušte pouze tento odběr; proces poběží dál.

ProcessLogEvent

type ProcessLogEvent =
	| {
			type: "stdout" | "stderr";
			cursor: string;
			timestamp: string;
			data: Uint8Array;
	  }
	| {
			type: "terminal";
			state: "exited";
			cursor: string;
			timestamp: string;
			exit: ProcessExit;
	  }
	| {
			type: "terminal";
			state: "error";
			cursor: string;
			timestamp: string;
			error: ProcessFailure;
	  }
	| {
			type: "truncated";
			cursor?: string;
			timestamp: string;
	  };

Ponechte nejnovější cursor z doručených událostí, pokud pozdější požadavek Workeru pokračuje s logs({ since: cursor, replay: true, follow: true }) na stejný proces v stejný kontejner.

const process = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

const stream = await process.logs({ follow: true, replay: true });
const reader = stream.getReader();
const decoder = new TextDecoder();

for (;;) {
	const { done, value } = await reader.read();
	if (done) break;

	if (value.type === "stdout" || value.type === "stderr") {
		// Keep value.cursor if you will resume later
		console.log(value.type, decoder.decode(value.data, { stream: true }));
		continue;
	}

	if (value.type === "terminal") {
		console.log("done", value.state);
		break;
	}
}
const process = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

const stream = await process.logs({ follow: true, replay: true });
const reader = stream.getReader();
const decoder = new TextDecoder();

for (;;) {
	const { done, value } = await reader.read();
	if (done) break;

	if (value.type === "stdout" || value.type === "stderr") {
		// Keep value.cursor if you will resume later
		console.log(value.type, decoder.decode(value.data, { stream: true }));
		continue;
	}

	if (value.type === "terminal") {
		console.log("done", value.state);
		break;
	}
}

waitForExit()

Počkejte, až se sledovaná skupina procesů ustálí.

waitForExit(options?: {
	timeout?: number;
	signal?: AbortSignal;
}): Promise<ProcessExit>
Pole Typ Popis
timeout number Pouze lokální lhůta čekání; proces se neukončí.
signal AbortSignal Zrušte pouze toto čekání; proces tím neukončíte.

Vrátí ProcessExit. Místní vypršení časového limitu se projeví jako ProcessWaitTimeoutError. Místní přerušení se projeví jako ProcessAbortedError.

const build = await sandbox.exec(["/bin/bash", "-lc", "npm run build"], {
	cwd: "/workspace/app",
});
const exit = await build.waitForExit({ timeout: 600_000 });
console.log(exit.code, exit.signal, exit.timedOut);
const build = await sandbox.exec(["/bin/bash", "-lc", "npm run build"], {
	cwd: "/workspace/app",
});
const exit = await build.waitForExit({ timeout: 600_000 });
console.log(exit.code, exit.signal, exit.timedOut);

waitForLog()

Počkejte, až stdout a/nebo stderr odpovídá danému vzoru.

waitForLog(
	pattern: string | RegExp,
	options?: WaitForLogOptions,
): Promise<WaitForLogResult>

WaitForLogOptions

Pole Typ Popis
stream "stdout" | "stderr" | "both" Které streamy se mají shodovat. Výchozí: "both".
timeout number Pouze lokální lhůta čekání; proces se neukončí.
signal AbortSignal Zrušte pouze toto čekání; proces tím neukončíte.

WaitForLogResult

interface WaitForLogResult {
	stream: "stdout" | "stderr";
	text: string;
	match: string;
	cursor?: string;
}

Pokud proces skončí dříve, než dojde ke shodě, SDK vyvolá ProcessExitedBeforeLogError. Místní časový limit čekání vyvolá ProcessWaitTimeoutError.

const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

const ready = await server.waitForLog(/listening on/i, {
	stream: "both",
	timeout: 60_000,
});
console.log(ready.stream, ready.match);
const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

const ready = await server.waitForLog(/listening on/i, {
	stream: "both",
	timeout: 60_000,
});
console.log(ready.stream, ready.match);

waitForPort()

Počkejte, až bude port připraven, nebo selžte, pokud proces skončí dříve nebo pokud skončí lokální čekání.

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

WaitForPortOptions

Pole Typ Popis
mode "tcp" | "http" Kontrola připravenosti. Výchozí hodnota: "tcp" (přijímá TCP spojení).
path string Cesta HTTP pro požadavek, když mode je "http". Výchozí hodnota: "/".
status number | { min: number; max: number } Očekávaný stav HTTP nebo uzavřený rozsah, když mode je "http". Výchozí hodnota: { min: 200, max: 399 }.
interval number Milisekundy mezi kontrolami. Výchozí hodnota: 500.
timeout number Pouze lokální lhůta čekání; proces se neukončí. Při vynechání neplatí žádný výchozí časový limit.
signal AbortSignal Zrušte pouze toto čekání; proces tím neukončíte.

Režim TCP (výchozí) je úspěšná, jakmile port přijme spojení:

const db = await sandbox.exec(["redis-server"]);

await db.waitForPort(6379, {
	mode: "tcp",
	timeout: 10_000,
});
const db = await sandbox.exec(["redis-server"]);

await db.waitForPort(6379, {
	mode: "tcp",
	timeout: 10_000,
});

Režim HTTP odešle HTTP požadavek a zkontroluje stav odpovědi:

const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

await server.waitForPort(3000, {
	mode: "http",
	path: "/health",
	status: { min: 200, max: 299 },
	timeout: 60_000,
});
const server = await sandbox.exec(["/bin/bash", "-lc", "npm run dev"], {
	cwd: "/workspace/app",
});

await server.waitForPort(3000, {
	mode: "http",
	path: "/health",
	status: { min: 200, max: 299 },
	timeout: 60_000,
});

Typická selhání:

kill()

Odešlete procesu číselný signál.

kill(signal?: number): Promise<void>

Výchozí signal je 15 (SIGTERM). Předejte pouze číselný signál (například 9 pro SIGKILL). Řetězcové názvy signálů nejsou podporovány.

Zastavení procesu je nezávislé na zrušení lokálního čekání nebo odběru logů.

exitCode

readonly exitCode: Promise<number>

Vyřeší se s návratovým kódem ve chvíli, kdy se sledovaná skupina procesů ustálí (stejná hranice dokončení jako u waitForExit()). Upřednostněte waitForExit() když navíc potřebujete signal nebo timedOut.

ProcessStatus

type ProcessStatus =
	| {
			state: "running";
			id: string;
			pid: number;
			command: SandboxCommand;
			cwd?: string;
			startedAt: string;
	  }
	| {
			state: "exited";
			id: string;
			pid: number;
			command: SandboxCommand;
			cwd?: string;
			startedAt: string;
			endedAt: string;
			exit: ProcessExit;
	  }
	| {
			state: "error";
			id: string;
			pid: number;
			command: SandboxCommand;
			cwd?: string;
			startedAt: string;
			endedAt: string;
			error: ProcessFailure;
	  };

listProcesses() vrací ProcessStatus[] s touto strukturou.

ProcessExit

Pozorovaný výsledek pro kořen podproces, jakmile se sledovaná skupina ustálí.

interface ProcessExit {
	code: number;
	signal?: number;
	timedOut: boolean;
}

Signály doručené pouze potomkům tento výsledek nemění. Viz Provádění procesů.

ProcessFailure

interface ProcessFailure {
	code: string;
	message: string;
}

Časté chyby

getProcess a listProcesses nevyvolávají chybu pro chybějící úlohu. Vrací null nebo [] když neběží žádný kontejner, když je ID v aktuálním kontejneru neznámé nebo když proces patřil předchozímu kontejneru. Následující třídy chyb platí pro operace nad handle procesu (a pro spuštění), nikoli pro tato vyhledávání.

Situace Třída / výsledek
getProcess / listProcesses zatímco neběží žádný kontejner null / [] (nejde o chybu; nespouští kontejner)
getProcess pro neznámé ID nebo proces z předchozího kontejneru null
Operace na handle poté, co byl kontejner nahrazen StaleProcessHandleError
Operace na handle, když proces v aktuálním kontejneru už neexistuje ProcessNotFoundError
Vypršel časový limit lokálního čekání (output / waitForExit / waitForLog) ProcessWaitTimeoutError
Lokální AbortSignal u čekání nebo streamu ProcessAbortedError
Port nebyl připravený před vypršením místního časového limitu ProcessReadyTimeoutError
Proces skončil dříve, než byl port připravený ProcessExitedBeforeReadyError
Proces skončil dříve, než došlo ke shodě v protokolu ProcessExitedBeforeLogError
Neplatný pracovní adresář při spuštění InvalidProcessCwdError
Neplatné prostředí při spuštění InvalidProcessEnvironmentError
Neplatný kurzor protokolu InvalidProcessCursorError
Spuštění procesu se nezdařilo ProcessSpawnFailedError
Kontejner není připraven; práce nebyla zahájena ContainerUnavailableError
Práce přerušená poté, co už možná začala OperationInterruptedError

Pokyny k obnovení: Chyby a zotavení. Úplný katalog: API chyb. Životnost: Jak dlouho proces žije.