Back to Microsandbox

Execution

docs/sdk/rust/execution.mdx

0.5.1045.7 KB
Original Source

Run commands inside a running sandbox: buffer the output in one call, stream it event by event, drive a shell, or bridge your terminal to an interactive PTY session. See Commands for usage examples.

<div className="msb-glance"> <p className="msb-gl"><span className="msb-dot instance"></span>Run · buffered<span className="msb-ct">4</span></p> <a className="msb-row" href="#sb-exec"><span className="msb-rn">sb.exec()</span><span className="msb-rg">run, wait, collect output</span></a> <a className="msb-row" href="#sb-exec_with"><span className="msb-rn">sb.exec_with()</span><span className="msb-rg">run with per-exec options</span></a> <a className="msb-row" href="#sb-shell"><span className="msb-rn">sb.shell()</span><span className="msb-rg">run through the shell</span></a> <a className="msb-row" href="#sb-shell_with"><span className="msb-rn">sb.shell_with()</span><span className="msb-rg">shell with options</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Run · streaming<span className="msb-ct">4</span></p> <a className="msb-row" href="#sb-exec_stream"><span className="msb-rn">sb.exec_stream()</span><span className="msb-rg">stream stdout/stderr events</span></a> <a className="msb-row" href="#sb-exec_stream_with"><span className="msb-rn">sb.exec_stream_with()</span><span className="msb-rg">stream with options</span></a> <a className="msb-row" href="#sb-shell_stream"><span className="msb-rn">sb.shell_stream()</span><span className="msb-rg">stream a shell command</span></a> <a className="msb-row" href="#sb-shell_stream_with"><span className="msb-rn">sb.shell_stream_with()</span><span className="msb-rg">stream shell with options</span></a> <p className="msb-gl"><span className="msb-dot instance"></span>Attach · interactive<span className="msb-ct">3</span></p> <a className="msb-row" href="#sb-attach"><span className="msb-rn">sb.attach()</span><span className="msb-rg">bridge terminal to a process</span></a> <a className="msb-row" href="#sb-attach_with"><span className="msb-rn">sb.attach_with()</span><span className="msb-rg">attach with options</span></a> <a className="msb-row" href="#sb-attach_shell"><span className="msb-rn">sb.attach_shell()</span><span className="msb-rg">attach to the default shell</span></a> <p className="msb-gl"><span className="msb-dot builder"></span>Builder · ExecOptionsBuilder<span className="msb-ct">14</span></p> <div className="msb-chiprow"> <a className="msb-chip" href="#arg">.arg()</a> <a className="msb-chip" href="#args">.args()</a> <a className="msb-chip" href="#cwd">.cwd()</a> <a className="msb-chip" href="#user">.user()</a> <a className="msb-chip" href="#env">.env()</a> <a className="msb-chip" href="#envs">.envs()</a> <a className="msb-chip" href="#timeout">.timeout()</a> <a className="msb-chip" href="#tty">.tty()</a> <a className="msb-chip" href="#stdin_null">.stdin_null()</a> <a className="msb-chip" href="#stdin_pipe">.stdin_pipe()</a> <a className="msb-chip" href="#stdin_bytes">.stdin_bytes()</a> <a className="msb-chip" href="#rlimit">.rlimit()</a> <a className="msb-chip" href="#rlimit_range">.rlimit_range()</a> <a className="msb-chip" href="#build">.build()</a> </div> <p className="msb-gl"><span className="msb-dot builder"></span>Builder · AttachOptionsBuilder<span className="msb-ct">10</span></p> <div className="msb-chiprow"> <a className="msb-chip" href="#arg-2">.arg()</a> <a className="msb-chip" href="#args-2">.args()</a> <a className="msb-chip" href="#cwd-2">.cwd()</a> <a className="msb-chip" href="#user-2">.user()</a> <a className="msb-chip" href="#env-2">.env()</a> <a className="msb-chip" href="#envs-2">.envs()</a> <a className="msb-chip" href="#detach_keys">.detach_keys()</a> <a className="msb-chip" href="#rlimit-3">.rlimit()</a> <a className="msb-chip" href="#rlimit_range-2">.rlimit_range()</a> <a className="msb-chip" href="#build-2">.build()</a> </div> <p className="msb-gl"><span className="msb-dot type"></span>Types</p> <div className="msb-chiprow"> <a className="msb-typepill" href="#exechandle">ExecHandle</a> <a className="msb-typepill" href="#execcontrol">ExecControl</a> <a className="msb-typepill" href="#execsink">ExecSink</a> <a className="msb-typepill" href="#execevent">ExecEvent</a> <a className="msb-typepill" href="#execoutput">ExecOutput</a> <a className="msb-typepill" href="#exitstatus">ExitStatus</a> <a className="msb-typepill" href="#rlimit-2">Rlimit</a> <a className="msb-typepill" href="#rlimitresource">RlimitResource</a> </div> </div> <p className="msb-label" id="typical-flow">Typical flow</p>
rust
use microsandbox::Sandbox;

let sb = Sandbox::builder("api").image("python").create().await?;

// Buffered: run and collect everything
let out = sb.exec("python", ["-c", "print('hi')"]).await?;
println!("{}", out.stdout()?);

// Streaming: process output as it arrives
let mut handle = sb.exec_stream("tail", ["-f", "/var/log/app.log"]).await?;
while let Some(event) = handle.recv().await {
    if let microsandbox::ExecEvent::Stdout(chunk) = event {
        print!("{}", String::from_utf8_lossy(&chunk));
    }
}

sb.stop().await?;

Run methods


<span className="msb-recv">sb.</span><span className="msb-hn">exec()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn exec(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<ExecOutput>

Run a command inside the sandbox and wait for it to complete. Collects all stdout and stderr into memory and returns them along with the exit status. cmd is passed literally to the guest agent: the image ENTRYPOINT is not consulted, and args are not shell-interpreted. For long-running processes or large output, use exec_stream(); for shell syntax like pipes and redirects, use shell().

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to execute, e.g. <code>"python"</code> or <code>"/usr/bin/node"</code>.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Command arguments, e.g. <code>["-c", "print('hi')"]</code>.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#execoutput">ExecOutput</a></div> <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div> </div> </div> <Accordion title="Example">
rust
let out = sb.exec("python", ["-V"]).await?;
println!("{}", out.stdout()?);
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">exec_with()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn exec_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecOutput>

Run a command with per-execution overrides and wait for completion. The closure receives an ExecOptionsBuilder to set args, working directory, environment variables, user, timeout, resource limits, stdin mode, and TTY allocation. These overrides apply only to this execution and don't change the sandbox's defaults.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to execute.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div> <div className="msb-param-desc">Configure execution options.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#execoutput">ExecOutput</a></div> <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div> </div> </div> <Accordion title="Example">
rust
use std::time::Duration;

let out = sb.exec_with("python", |e| e
    .args(["compute.py"])
    .cwd("/app")
    .env("LOG_LEVEL", "debug")
    .timeout(Duration::from_secs(30)))
    .await?;
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">shell()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn shell(&self, script: impl Into<String>) -> MicrosandboxResult<ExecOutput>

Run a command through the sandbox's configured shell (default: /bin/sh, set via SandboxBuilder::shell()). The script is run as <shell> -c "<script>", so shell syntax like pipes, redirects, and && chains works.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Shell command string, e.g. <code>"ls -la /app && echo done"</code>.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#execoutput">ExecOutput</a></div> <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div> </div> </div> <Accordion title="Example">
rust
let out = sb.shell("cat /etc/os-release | grep PRETTY_NAME").await?;
println!("{}", out.stdout()?);
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">shell_with()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn shell_with(
    &self,
    script: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecOutput>

Run a shell command with per-execution overrides and wait for completion. The -c <script> arguments are prepended to whatever the ExecOptionsBuilder configures, so use the builder for env, cwd, user, timeout, and resource limits rather than for positional args.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Shell command string.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div> <div className="msb-param-desc">Configure execution options.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#execoutput">ExecOutput</a></div> <div className="msb-param-desc">Collected stdout, stderr, and exit status.</div> </div> </div> <Accordion title="Example">
rust
let out = sb.shell_with("env | sort", |e| e.env("STAGE", "build")).await?;
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">exec_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn exec_stream(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<ExecHandle>

Run a command with streaming output. Returns an ExecHandle that emits stdout, stderr, started, and exit events as they happen, rather than buffering everything until the command finishes. Use this for long-running processes, large output, or when you need to process output incrementally.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to execute.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Command arguments.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#exechandle">ExecHandle</a></div> <div className="msb-param-desc">Streaming handle for receiving events and controlling the process.</div> </div> </div> <Accordion title="Example">
rust
use microsandbox::ExecEvent;

let mut handle = sb.exec_stream("tail", ["-f", "/var/log/app.log"]).await?;
while let Some(event) = handle.recv().await {
    match event {
        ExecEvent::Stdout(chunk) => print!("{}", String::from_utf8_lossy(&chunk)),
        ExecEvent::Exited { code } => { println!("exited {code}"); break; }
        _ => {}
    }
}
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">exec_stream_with()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn exec_stream_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecHandle>

Streaming execution with per-execution overrides. Enable stdin_pipe() to write to the process's stdin via ExecHandle::take_stdin(), and tty(true) to allocate a pseudo-terminal for interactive programs like shells, REPLs, or editors.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to execute.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div> <div className="msb-param-desc">Configure execution options.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#exechandle">ExecHandle</a></div> <div className="msb-param-desc">Streaming handle.</div> </div> </div> <Accordion title="Example">
rust
let mut handle = sb.exec_stream_with("python", |e| e.stdin_pipe().tty(true)).await?;
if let Some(stdin) = handle.take_stdin() {
    stdin.write(b"print(2 + 2)\n").await?;
    stdin.close().await?;
}
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">shell_stream()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn shell_stream(&self, script: impl Into<String>) -> MicrosandboxResult<ExecHandle>

Like shell(), but returns a streaming ExecHandle instead of waiting for completion.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Shell command string.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#exechandle">ExecHandle</a></div> <div className="msb-param-desc">Streaming handle.</div> </div> </div> <Accordion title="Example">
rust
let mut handle = sb.shell_stream("for i in 1 2 3; do echo $i; sleep 1; done").await?;
let out = handle.collect().await?;
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">shell_stream_with()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn shell_stream_with(
    &self,
    script: impl Into<String>,
    f: impl FnOnce(ExecOptionsBuilder) -> ExecOptionsBuilder,
) -> MicrosandboxResult<ExecHandle>

Run a shell command with per-execution overrides and streaming I/O. As with shell_with(), the -c <script> arguments are prepended to whatever the builder configures.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>script</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Shell command string.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#execoptionsbuilder">FnOnce(ExecOptionsBuilder)</a></div> <div className="msb-param-desc">Configure execution options.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><a className="msb-type" href="#exechandle">ExecHandle</a></div> <div className="msb-param-desc">Streaming handle.</div> </div> </div> <Accordion title="Example">
rust
let mut handle = sb.shell_stream_with("npm run build", |e| e.cwd("/app")).await?;
</Accordion>

Attach methods


<span className="msb-recv">sb.</span><span className="msb-hn">attach()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn attach(
    &self,
    cmd: impl Into<String>,
    args: impl IntoIterator<Item = impl Into<String>>,
) -> MicrosandboxResult<i32>

Bridge your terminal directly to a process inside the sandbox for a fully interactive PTY session. The host terminal is put into raw mode and its stdin, stdout, and window-size changes are wired to the guest process. Press the detach key (default Ctrl+]) to disconnect without stopping the process; it keeps running in the guest. Returns when the process exits or you detach.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to run.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Command arguments.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">i32</span></div> <div className="msb-param-desc">Exit code of the process, or <code>-1</code> if you detached before it exited.</div> </div> </div> <Accordion title="Example">
rust
let exit_code = sb.attach("bash", ["-l"]).await?;
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">attach_with()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn attach_with(
    &self,
    cmd: impl Into<String>,
    f: impl FnOnce(AttachOptionsBuilder) -> AttachOptionsBuilder,
) -> MicrosandboxResult<i32>

Interactive PTY attach with options. The closure receives an AttachOptionsBuilder to set args, environment variables, working directory, user, custom detach keys, and resource limits.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cmd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Command to run.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>f</code><a className="msb-type" href="#attachoptionsbuilder">FnOnce(AttachOptionsBuilder)</a></div> <div className="msb-param-desc">Configure attach options.</div> </div> </div> <p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">i32</span></div> <div className="msb-param-desc">Exit code of the process, or <code>-1</code> if you detached.</div> </div> </div> <Accordion title="Example">
rust
let exit_code = sb.attach_with("zsh", |a| a
    .env("TERM", "xterm-256color")
    .detach_keys("ctrl-p,ctrl-q"))
    .await?;
</Accordion>

<span className="msb-recv">sb.</span><span className="msb-hn">attach_shell()</span>

<div className="msb-tags"><span className="msb-tag is-instance">instance</span><span className="msb-tag is-async">async</span></div>
rust
async fn attach_shell(&self) -> MicrosandboxResult<i32>

Attach to the sandbox's default shell (configured via SandboxBuilder::shell(), default /bin/sh) with an interactive PTY session.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">i32</span></div> <div className="msb-param-desc">Exit code, or <code>-1</code> if you detached.</div> </div> </div> <Accordion title="Example">
rust
let exit_code = sb.attach_shell().await?;
</Accordion>

ExecOptionsBuilder

Builder for per-execution overrides passed to exec_with(), exec_stream_with(), shell_with(), and shell_stream_with(). Does not change the sandbox's defaults. Every setter returns Self, so calls chain.


<span className="msb-recv">.</span><span className="msb-hn">arg()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn arg(self, arg: impl Into<String>) -> Self

Append a single command-line argument, e.g. "-la" or "/tmp".

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>arg</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Argument to append.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">args()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn args(self, args: impl IntoIterator<Item = impl Into<String>>) -> Self

Append multiple command-line arguments.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Arguments to append.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">cwd()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn cwd(self, cwd: impl Into<String>) -> Self

Override the working directory for this command. Overrides the sandbox default set via the builder's workdir.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cwd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">user()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn user(self, user: impl Into<String>) -> Self

Override the guest user for this command.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>user</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">User name or UID.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">env()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self

Set an environment variable for this command. Merged on top of the sandbox-level env vars.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Variable name.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Variable value.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">envs()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn envs(
    self,
    vars: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self

Set multiple environment variables for this command at once.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>vars</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Key-value pairs to set.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">timeout()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn timeout(self, timeout: Duration) -> Self

Kill the process with SIGKILL if it hasn't exited within this duration.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>timeout</code><span className="msb-type">Duration</span></div> <div className="msb-param-desc">Maximum run time before SIGKILL.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">tty()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn tty(self, enabled: bool) -> Self

Allocate a pseudo-terminal. Enable for interactive programs (shells, editors, top); disable for scripts and batch jobs. When enabled, stdout and stderr are merged at the kernel level inside the guest. Default: false.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>enabled</code><span className="msb-type">bool</span></div> <div className="msb-param-desc"><code>true</code> to allocate a PTY.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">stdin_null()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn stdin_null(self) -> Self

Stdin reads from /dev/null. This is the default.


<span className="msb-recv">.</span><span className="msb-hn">stdin_pipe()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn stdin_pipe(self) -> Self

Enable a stdin writer via ExecSink. Use with ExecHandle::take_stdin() on the returned streaming handle to send data to the process.


<span className="msb-recv">.</span><span className="msb-hn">stdin_bytes()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn stdin_bytes(self, data: impl Into<Vec<u8>>) -> Self

Provide fixed bytes as stdin. The process reads them and then sees EOF.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>data</code><span className="msb-type">impl Into&lt;Vec&lt;u8&gt;&gt;</span></div> <div className="msb-param-desc">Bytes fed to the process's stdin.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">rlimit()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn rlimit(self, resource: RlimitResource, limit: u64) -> Self

Set a POSIX resource limit with soft equal to hard. Applied via setrlimit() before exec.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div> <div className="msb-param-desc">Which resource to limit.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>limit</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Limit value (soft = hard).</div> </div> </div> <Accordion title="Example">
rust
use microsandbox::sandbox::RlimitResource;

let out = sb.exec_with("./worker", |e| e.rlimit(RlimitResource::Nofile, 1024)).await?;
</Accordion>

<span className="msb-recv">.</span><span className="msb-hn">rlimit_range()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn rlimit_range(self, resource: RlimitResource, soft: u64, hard: u64) -> Self

Set a resource limit with different soft and hard values. build() errors if soft > hard.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div> <div className="msb-param-desc">Which resource to limit.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>soft</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Soft limit (raisable by the process up to hard).</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>hard</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Hard ceiling.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">build()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn build(self) -> MicrosandboxResult<ExecOptions>

Finalize the options. Called automatically by the *_with methods when you use the closure form. Returns an error if any rlimit has soft > hard.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">ExecOptions</span></div> <div className="msb-param-desc">Validated execution options.</div> </div> </div>

AttachOptionsBuilder

Builder for interactive attach options passed to attach_with(). Every setter returns Self, so calls chain.


<span className="msb-recv">.</span><span className="msb-hn">arg()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn arg(self, arg: impl Into<String>) -> Self

Append a single command-line argument to the attached command.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>arg</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Argument to append.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">args()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn args(self, args: impl IntoIterator<Item = impl Into<String>>) -> Self

Append multiple command-line arguments.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>args</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Arguments to append.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">cwd()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn cwd(self, cwd: impl Into<String>) -> Self

Override the working directory for the attached session.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>cwd</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Absolute path inside the guest.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">user()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn user(self, user: impl Into<String>) -> Self

Override the guest user for the attached session.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>user</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">User name or UID.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">env()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn env(self, key: impl Into<String>, value: impl Into<String>) -> Self

Set an environment variable for the attached session. Merged on top of the sandbox-level env vars.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>key</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Variable name.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>value</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Variable value.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">envs()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn envs(
    self,
    vars: impl IntoIterator<Item = (impl Into<String>, impl Into<String>)>,
) -> Self

Set multiple environment variables for the attached session at once.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>vars</code><span className="msb-type">impl IntoIterator</span></div> <div className="msb-param-desc">Key-value pairs to set.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">detach_keys()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn detach_keys(self, keys: impl Into<String>) -> Self

Set the key sequence that detaches from the session without stopping the process. Docker-style syntax: "ctrl-]" (default), "ctrl-p,ctrl-q" for a multi-key sequence, or a single character like "q".

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>keys</code><span className="msb-type">impl Into&lt;String&gt;</span></div> <div className="msb-param-desc">Detach key specification.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">rlimit()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn rlimit(self, resource: RlimitResource, limit: u64) -> Self

Set a POSIX resource limit with soft equal to hard for the attached process.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div> <div className="msb-param-desc">Which resource to limit.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>limit</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Limit value (soft = hard).</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">rlimit_range()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn rlimit_range(self, resource: RlimitResource, soft: u64, hard: u64) -> Self

Set a resource limit with different soft and hard values for the attached process. build() errors if soft > hard.

<p className="msb-label">Parameters</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><code>resource</code><a className="msb-type" href="#rlimitresource">RlimitResource</a></div> <div className="msb-param-desc">Which resource to limit.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>soft</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Soft limit.</div> </div> <div className="msb-param"> <div className="msb-param-key"><code>hard</code><span className="msb-type">u64</span></div> <div className="msb-param-desc">Hard ceiling.</div> </div> </div>

<span className="msb-recv">.</span><span className="msb-hn">build()</span>

<div className="msb-tags"><span className="msb-tag is-builder">builder</span></div>
rust
fn build(self) -> MicrosandboxResult<AttachOptions>

Finalize the options. Called automatically by attach_with(). Returns an error if any rlimit has soft > hard.

<p className="msb-label">Returns</p> <div className="msb-params"> <div className="msb-param"> <div className="msb-param-key"><span className="msb-type">AttachOptions</span></div> <div className="msb-param-desc">Validated attach options.</div> </div> </div>

Types

ExecHandle

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#sb-exec_stream">exec_stream()</a> · <a href="#sb-exec_stream_with">exec_stream_with()</a> · <a href="#sb-shell_stream">shell_stream()</a> · <a href="#sb-shell_stream_with">shell_stream_with()</a></p>

A handle to a running streaming execution. Receives ExecEvents as the process produces output, and provides control over stdin, signals, and the PTY size.

MethodReturnsDescription
recv()Option<ExecEvent>Receive the next event. None when the session has ended and all output has been delivered.
wait()Result<ExitStatus>Wait for the process to exit, discarding any remaining output.
collect()Result<ExecOutput>Wait for exit and collect all remaining stdout/stderr.
id()StringSession ID for this execution. Can be used to reattach later.
control()ExecControlA cloneable control handle for sending signals and resizes from another task.
take_stdin()Option<ExecSink>Take the stdin writer. Only available if stdin_pipe() was set; returns None after the first call.
signal(signal)Result<()>Send a POSIX signal to the process (e.g. libc::SIGTERM).
kill()Result<()>Send SIGKILL to the process.
resize(rows, cols)Result<()>Resize the PTY for this session.

ExecControl

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.control()</a></p>

A cloneable, lightweight control handle for a streaming exec session. Lets a task other than the one owning the ExecHandle send signals and PTY resizes. Carries no event stream.

MethodReturnsDescription
id()StringSession ID for this execution.
signal(signal)Result<()>Send a POSIX signal to the process (e.g. libc::SIGTERM).
kill()Result<()>Send SIGKILL to the process.
resize(rows, cols)Result<()>Resize the PTY for this session.

ExecSink

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.take_stdin()</a></p>

A writer for sending data to a running process's stdin. Obtained via ExecHandle::take_stdin() after enabling stdin_pipe().

MethodParametersDescription
write(data)data: impl AsRef<[u8]>Write bytes to the process's stdin.
close()-Close stdin. The process sees EOF on its stdin.

ExecEvent

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Yielded by <a href="#exechandle">ExecHandle.recv()</a></p>

An event emitted by a streaming execution.

VariantFieldsDescription
Startedpid: u32The process has started. pid is the guest-side PID.
StdoutBytesA chunk of stdout data. May arrive in arbitrary sizes.
StderrBytesA chunk of stderr data.
Exitedcode: i32The process exited normally. code is the exit code.
FailedExecFailedThe process failed to spawn (binary not found, permission denied, etc.). The user code never ran. Terminal: no further events follow.
StdinErrorExecStdinErrorA stdin write to the child failed (e.g. broken pipe). Non-terminal: the session keeps running and may still emit output and an Exited event.

ExecOutput

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#sb-exec">exec()</a> · <a href="#sb-exec_with">exec_with()</a> · <a href="#sb-shell">shell()</a> · <a href="#sb-shell_with">shell_with()</a> · <a href="#exechandle">ExecHandle.collect()</a></p>

The result of a completed command execution. Holds the exit status and all captured output.

MethodReturnsDescription
status()ExitStatusExit code and success flag.
stdout()Result<String, FromUtf8Error>Collected stdout decoded as UTF-8. Errors if the output is not valid UTF-8.
stderr()Result<String, FromUtf8Error>Collected stderr decoded as UTF-8.
stdout_bytes()&BytesRaw stdout bytes without decoding.
stderr_bytes()&BytesRaw stderr bytes without decoding.

ExitStatus

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Returned by <a href="#exechandle">ExecHandle.wait()</a> · <a href="#execoutput">ExecOutput.status()</a> · <a href="/sdk/rust/sandbox#sb-wait">sb.wait()</a> · <a href="/sdk/rust/sandbox#sb-stop_and_wait">sb.stop_and_wait()</a></p>

The exit status of a completed process.

FieldTypeDescription
codei32Exit code. 0 typically means success.
successbooltrue if code is 0.

Rlimit

<div className="msb-tags"><span className="msb-tag is-type">struct</span></div> <p className="msb-backref">Configured via <a href="#rlimit">rlimit()</a> · <a href="#rlimit_range">rlimit_range()</a></p>

A POSIX resource limit. Built indirectly by rlimit() and rlimit_range() on the option builders; you rarely construct it by hand.

FieldTypeDescription
resourceRlimitResourceWhich resource to limit.
softu64Soft limit; the process may raise it up to hard.
hardu64Hard ceiling; raising it requires privileges.

RlimitResource

<div className="msb-tags"><span className="msb-tag is-type">enum</span></div> <p className="msb-backref">Used by <a href="#rlimit">rlimit()</a> · <a href="#rlimit_range">rlimit_range()</a> · <a href="#rlimit-3">AttachOptionsBuilder.rlimit()</a></p>

POSIX resource limit identifiers. Each maps to an RLIMIT_* constant.

ValueDescription
CpuMax CPU time in seconds (RLIMIT_CPU)
FsizeMax file size in bytes (RLIMIT_FSIZE)
DataMax data segment size (RLIMIT_DATA)
StackMax stack size (RLIMIT_STACK)
CoreMax core file size (RLIMIT_CORE)
RssMax resident set size (RLIMIT_RSS)
NprocMax number of processes (RLIMIT_NPROC)
NofileMax open file descriptors (RLIMIT_NOFILE)
MemlockMax locked memory (RLIMIT_MEMLOCK)
AsMax address space size (RLIMIT_AS)
LocksMax file locks (RLIMIT_LOCKS)
SigpendingMax pending signals (RLIMIT_SIGPENDING)
MsgqueueMax bytes in POSIX message queues (RLIMIT_MSGQUEUE)
NiceMax nice priority (RLIMIT_NICE)
RtprioMax real-time priority (RLIMIT_RTPRIO)
RttimeMax real-time timeout (RLIMIT_RTTIME)