Processes

Run, spawn and attach to processes in a sandbox through cua-spacesd.

Run a command to completion with run or sh, or spawn a SpacesdProcess to stream its output and write its input.

Python programs usually use the high-level API instead: sb.shell, sb.terminal.

Run processes#

Methods of SpacesdClient.

SpacesdClient.run#

Runs a command to completion.

async def run(self, command: SpacesdCommand) -> ProcessOutput
ParameterTypeDefault
commandSpacesdCommandrequired

Returns ProcessOutput · Async · Raises CuaError

Example

import asyncio
 
import cua
 
async def main():
    guest = await cua.embedded().spacesd(URL, TOKEN)  # or: await sandbox.spacesd(None)
    out = await guest.run(cua.SpacesdCommand(program="echo", args=["hello"]))
    print([out.exit.success, out.stdout])
    # [True, b'hello\n']
 
asyncio.run(main())

SpacesdClient.sh#

Runs line with /bin/sh -c to completion.

async def sh(self, line: str, timeout_ms: Optional[int]) -> ProcessOutput
ParameterTypeDefault
lineStringrequired
timeout_msOption<u32>required

Returns ProcessOutput · Async · Raises CuaError

SpacesdClient.spawn#

Starts a command and returns its handle.

async def spawn(self, command: SpacesdCommand) -> SpacesdProcess
ParameterTypeDefault
commandSpacesdCommandrequired

Returns SpacesdProcess · Async · Raises CuaError

Example

import asyncio
 
import cua
 
async def main():
    guest = await cua.embedded().spacesd(URL, TOKEN)
    proc = await guest.spawn(cua.SpacesdCommand(program="cat", args=[], stdin=True))
    await proc.write_stdin(b"xyz")
    await proc.close_stdin()
    print([(await proc.wait()).stdout])
    # [b'xyz']
 
asyncio.run(main())

SpacesdClient.attach#

Attaches to a running process by pid or tag.

async def attach(self, pid: Optional[int], tag: Optional[str], replay: ReplayMode) -> SpacesdProcess
ParameterTypeDefault
pidOption<u32>required
tagOption<String>required
replayReplayModerequired

Returns SpacesdProcess · Async · Raises CuaError

SpacesdClient.list_processes#

Guest processes as proto3 JSON ([ProcessInfo]).

async def list_processes(self, include_exited: bool) -> str
ParameterTypeDefault
include_exitedboolrequired

Returns String · Async · Raises CuaError

SpacesdProcess#

A guest process, from spawn or attach.

Returned by SpacesdClient.attach, SpacesdClient.spawn.

MethodDescription
close_stdinCloses stdin.
detachStops receiving output without affecting the process.
killSIGKILL to the process and its process group (what it started), including a command run as another user through sudo.
next_eventNext output chunk or the exit; None after the exit was returned.
resizeResizes the PTY.
signalSends a signal by name (term, kill, SIGINT, ...).
waitCollects the remaining output until exit.
write_ptyWrites PTY keystrokes.
write_stdinWrites stdin (PTY input for PTY processes), exactly once across retries.
AccessorReturnsDescription
pid()u32Guest pid.
tag()Option<String>Tag, when set.

SpacesdProcess.close_stdin#

Closes stdin.

async def close_stdin(self) -> None

Async · Raises CuaError

SpacesdProcess.detach#

Stops receiving output without affecting the process. A pending next_event returns None at once.

async def detach(self) -> None

Async

SpacesdProcess.kill#

SIGKILL to the process and its process group (what it started), including a command run as another user through sudo.

async def kill(self) -> None

Async · Raises CuaError

SpacesdProcess.next_event#

Next output chunk or the exit; None after the exit was returned. Reconnects transparently from the last seen offset.

async def next_event(self) -> Optional[ProcessEvent]

Returns Option<ProcessEvent> · Async · Raises CuaError

SpacesdProcess.resize#

Resizes the PTY.

async def resize(self, cols: int, rows: int) -> None
ParameterTypeDefault
colsu32required
rowsu32required

Async · Raises CuaError

SpacesdProcess.signal#

Sends a signal by name (term, kill, SIGINT, ...). With process_group, to the process's whole group (everything it started), as a terminal's Ctrl-C does; by default to the process alone.

async def signal(self, signal: str, process_group: bool = False) -> None
ParameterTypeDefault
signalStringrequired
process_groupboolfalse

Async · Raises CuaError

SpacesdProcess.wait#

Collects the remaining output until exit.

async def wait(self) -> ProcessOutput

Returns ProcessOutput · Async · Raises CuaError

SpacesdProcess.write_pty#

Writes PTY keystrokes.

async def write_pty(self, data: bytes) -> None
ParameterTypeDefault
dataVec<u8>required

Async · Raises CuaError

SpacesdProcess.write_stdin#

Writes stdin (PTY input for PTY processes), exactly once across retries.

async def write_stdin(self, data: bytes) -> None
ParameterTypeDefault
dataVec<u8>required

Async · Raises CuaError

SpacesdCommand record#

A command to run in the guest.

FieldTypeDefaultDescription
programStringProgram (absolute path or PATH lookup).
argsVec<String>[]Arguments.
envHashMap<String, String>[:]Extra environment.
cwdOption<String>NoneWorking directory.
userOption<String>NoneRun as this user.
timeout_ms / timeoutMsOption<u32>NoneKill after this long.
tagOption<String>NoneTag for reattaching (attach(tag=…)).
stdinboolfalseKeep stdin open for write_stdin.
ptyOption<PtySize>NoneRun in a PTY of this size.
request_id / requestIdOption<String>NoneIdempotency key: a later start with the same key reattaches to the running process or replays its recorded outcome instead of running the command again (the guest's exec ledger; see GetExecRecord).
epochOption<u64>NoneFencing epoch: a start with an epoch lower than the Space's current one is refused; a higher one advances it. None is unfenced.
scrollback_bytes / scrollbackBytesOption<u64>NoneSize of the guest's output scrollback ring for this process, in bytes. The ring never blocks the process: a reader that falls more than this far behind loses the evicted bytes (visible as an offset gap). None uses the server default (8 MiB); the server clamps larger requests to its maximum (512 MiB) rather than failing. The ring is allocated up to this size as output arrives, so the cost is bounded by the output actually produced.
kill_on_disconnect / killOnDisconnectboolfalseKill the process (term, then kill) when this client's connection to cua-spacesd ends before the process does, including when the client process dies. Off by default: processes are detached and can be reattached by tag.

ProcessOutput record#

Collected output of a finished process.

Returned by Sandbox.guest_sh, SpacesdClient.run, SpacesdClient.sh, SpacesdProcess.wait.

FieldTypeDefaultDescription
exitExitInfoExit.
stdoutVec<u8>stdout bytes.
stderrVec<u8>stderr bytes.
ptyVec<u8>PTY bytes.

ExitInfo record#

How a process ended.

FieldTypeDefaultDescription
codeOption<i32>Exit code for a normal exit.
signalOption<String>Terminating signal (kill, term, ...).
signal_number / signalNumberOption<i32>NoneRaw number of the terminating signal on the guest's OS, set for every signal death, also for those signal has no name for (SIGSEGV, SIGABRT, SIGPIPE, ...).
signal_name / signalNameOption<String>NoneConventional name of the terminating signal without SIG, in upper case ("SEGV", "ABRT"); independent of the guest's OS.
timed_out / timedOutboolStopped by its timeout.
errorOption<String>Supervisor error (for example "executable not found").
successboolcode == 0.

ProcessEvent record#

One output chunk or the exit.

Returned by SpacesdProcess.next_event.

FieldTypeDefaultDescription
kindProcessEventKindKind.
offsetu64Combined-output offset of the first byte.
dataVec<u8>Bytes (empty for Exit).
exitOption<ExitInfo>Exit (only for Exit).

ProcessEventKind enum#

Kind of a process event.

ProcessEventKind.STDOUT
ProcessEventKind.STDERR
ProcessEventKind.PTY
ProcessEventKind.EXIT
VariantDescription
Stdoutstdout bytes.
Stderrstderr bytes.
PtyPTY bytes.
ExitThe process ended (always last).

PtySize record#

A PTY size.

FieldTypeDefaultDescription
colsu32Columns.
rowsu32Rows.

ReplayMode enum#

Scrollback replay when attaching.

ReplayMode.NONE()
ReplayMode.ALL()
ReplayMode.LAST_BYTES(n: int)
ReplayMode.FROM_OFFSET(offset: int)
VariantDescription
NoneLive output only.
AllEverything retained.
LastBytesThe last n bytes. Fields: n: u64
FromOffsetFrom this combined-output offset. Fields: offset: u64