Skip to main content

Cmd

Struct Cmd 

Source
pub struct Cmd { /* private fields */ }
Expand description

Builder for a subprocess invocation or pipeline.

Construct via Cmd::new, configure with builder methods, chain with Cmd::pipe (or |), terminate with Cmd::run or Cmd::spawn.

Per-stage builders — arg, args, in_dir, env, envs, env_clear, env_remove — target the rightmost stage. Pipeline-level builders — stdin, stderr, timeout, deadline, retry, retry_when, secret, before_spawn — apply to the whole pipeline.

§Cloning

Cmd: Clone so you can build a base configuration and branch off variants. Most state is cheap to clone (owned data or Arc). One caveat: if stdin was set with StdinData::from_reader, the reader is shared across clones — whichever attempt runs first takes it, and later attempts (or other clones) see no stdin. For bytes-based stdin, every clone and every retry re-feeds the same buffer.

Implementations§

Source§

impl Cmd

Source

pub fn new(program: impl Into<OsString>) -> Cmd

Start a new command with the given program.

Source

pub fn pipe(self, next: Cmd) -> Cmd

Pipe this command’s stdout into next’s stdin.

Per-stage configuration (args, env, cwd) is preserved for each side. Pipeline-level configuration (stdin, stdout, stderr, timeout, deadline, retry, secret, before_spawn) is taken from selfany such settings on next are silently dropped.

§Gotcha
// WRONG: the inner `.timeout(...)` is discarded.
let _ = Cmd::new("a").pipe(Cmd::new("b").timeout(Duration::from_secs(5)));

// RIGHT: pipeline-level settings go on the outer `Cmd`.
let _ = Cmd::new("a").pipe(Cmd::new("b")).timeout(Duration::from_secs(5));
Source

pub fn arg(self, arg: impl Into<OsString>) -> Cmd

Append a single argument to the rightmost stage.

Source

pub fn args<I, S>(self, args: I) -> Cmd
where I: IntoIterator<Item = S>, S: Into<OsString>,

Append arguments to the rightmost stage.

Source

pub fn in_dir(self, dir: impl AsRef<Path>) -> Cmd

Set the working directory of the rightmost stage.

Source

pub fn env(self, key: impl Into<OsString>, value: impl Into<OsString>) -> Cmd

Add one environment variable to the rightmost stage.

Source

pub fn envs<I, K, V>(self, vars: I) -> Cmd
where I: IntoIterator<Item = (K, V)>, K: Into<OsString>, V: Into<OsString>,

Add multiple environment variables to the rightmost stage.

Source

pub fn env_remove(self, key: impl Into<OsString>) -> Cmd

Remove an environment variable from the rightmost stage.

Source

pub fn env_clear(self) -> Cmd

Clear the inherited environment of the rightmost stage.

Source

pub fn stdin(self, data: impl Into<StdinData>) -> Cmd

Feed data into the leftmost stage’s stdin.

Source

pub fn stderr(self, mode: Redirection) -> Cmd

Configure stderr routing for every stage. Default is Redirection::Capture.

Source

pub fn stdout(self, mode: Redirection) -> Cmd

Configure stdout routing for the last stage (for single commands, the only stage).

Default is Redirection::Capture, which populates RunOutput::stdout on run. Pick Redirection::Inherit to stream to the parent’s stdout, Redirection::Null to discard, or Redirection::File / Redirection::file to redirect to a file.

Setting non-Capture stdout is only supported on run. spawn / spawn_async always pipe stdout so the handle can expose it via take_stdout / the Read impl; a non-Capture stdout on the spawn path surfaces a RunError::Spawn with ErrorKind::InvalidInput.

Source

pub fn stderr_file(self, f: File) -> Cmd

Convenience: redirect stderr to a file without wrapping the File in Arc yourself. Shorthand for self.stderr(Redirection::file(f)).

Source

pub fn stdout_file(self, f: File) -> Cmd

Convenience: redirect stdout (of the last stage) to a file. Shorthand for self.stdout(Redirection::file(f)).

Source

pub fn timeout(self, timeout: Duration) -> Cmd

Kill this attempt after the given duration.

Source

pub fn deadline(self, deadline: Instant) -> Cmd

Kill if not done by this instant (composes across retries).

Source

pub fn retry(self, policy: RetryPolicy) -> Cmd

Attach a RetryPolicy. Defaults retry up to 3× on transient errors.

Source

pub fn retry_when( self, f: impl Fn(&RunError) -> bool + Send + Sync + 'static, ) -> Cmd

Replace the retry predicate without changing the backoff schedule.

Source

pub fn secret(self) -> Cmd

Mark the pipeline as containing secrets; CmdDisplay will render args as <secret>.

Source

pub fn before_spawn<F>(self, hook: F) -> Cmd
where F: Fn(&mut Command) -> Result<(), Error> + Send + Sync + 'static,

Register a hook called immediately before each spawn attempt.

The hook receives a &mut std::process::Command and may mutate it arbitrarily — set Unix-specific options via CommandExt (umask, pre_exec, process_group), attach IPC sockets, toggle environment late, etc. Returning an error aborts that spawn attempt and surfaces as RunError::Spawn.

§Scope
  • Sync path (run, spawn): hook fires per stage per retry attempt.
  • Async path (run_async, spawn_async): hook fires per stage per retry attempt. Tokio’s Command exposes its underlying std::process::Command via as_std_mut, so the same hook works on both paths — no parallel async hook type.
§Tokio-specific settings

Note that modifications made through as_std_mut do not include tokio’s own knobs (e.g., kill_on_drop). Those are set by procpilot internally and are not exposed to before_spawn.

Source

pub fn to_rightmost_command(&self) -> Command

Build a raw std::process::Command mirroring the rightmost stage.

For a single command this is the one you configured. For a pipeline, the upstream stages are discarded — the returned Command is only the rightmost one, without stdio wiring. Use to_commands to recover all stages.

The explicit name is a signpost: on a pipeline, this method silently drops information, so use it deliberately.

Source

pub fn to_commands(&self) -> Vec<Command>

Build one raw std::process::Command per stage, leftmost first.

Stdio wiring between stages is not set up — callers are responsible for piping the returned Commands together if they need the full shell-style behavior. For the typical case where you just want to execute the pipeline, use run or spawn.

Source

pub fn display(&self) -> CmdDisplay

Snapshot the command (or pipeline) for display/logging.

Source

pub fn spawn(self) -> Result<SpawnedProcess, RunError>

Spawn the command (or pipeline) as a long-lived process handle.

Returns a SpawnedProcess for streaming, bidirectional protocols, or any case where you need live access to stdin/stdout. Stdin and stdout are always piped; stderr follows the configured Redirection (default Redirection::Capture, drained into a background thread and surfaced on SpawnedProcess::wait).

For pipelines, SpawnedProcess::take_stdin targets the leftmost stage, SpawnedProcess::take_stdout the rightmost, and lifecycle methods operate on every stage.

If stdin bytes were set via stdin, they’re fed automatically in a background thread; otherwise the caller can pipe data via SpawnedProcess::take_stdin.

timeout, deadline, and retry are ignored on this path — they only apply to the one-shot run method. Use SpawnedProcess::wait_timeout or SpawnedProcess::kill for per-call bounds.

Source

pub fn spawn_and_collect_lines<F>(self, f: F) -> Result<RunOutput, RunError>
where F: FnMut(&str) -> Result<(), Error>,

Spawn and invoke f for each line of stdout as it arrives.

Returns the final RunOutput when the child exits, or a RunError::NonZeroExit if it exited non-zero. If f returns an error, the child is killed and the error is surfaced as RunError::Spawn.

Cmd::new("cargo")
    .args(["check", "--message-format=json"])
    .spawn_and_collect_lines(|line| {
        println!("{line}");
        Ok(())
    })?;
Source

pub fn run(self) -> Result<RunOutput, RunError>

Run the command (or pipeline) synchronously, blocking until it completes (or its timeout / deadline fires).

Returns RunOutput on exit status 0. Non-zero exits become RunError::NonZeroExit carrying the last 128 KiB of stdout/stderr. Spawn failures become RunError::Spawn; timeouts become RunError::Timeout.

For an async variant usable from inside a tokio runtime, enable the tokio feature and use run_async. For long-lived or streaming processes, see spawn.

§Examples

Basic capture:

let out = Cmd::new("git").args(["rev-parse", "HEAD"]).in_dir("/repo").run()?;
println!("{}", out.stdout_lossy().trim());

Typed error branching:

let maybe = match Cmd::new("git").args(["show", "possibly-missing"]).run() {
    Ok(out) => Some(out.stdout),
    Err(RunError::NonZeroExit { .. }) => None, // ref not found — expected
    Err(e) => return Err(e.into()),             // real failure
};

Pipeline with timeout and retry:

(Cmd::new("git").args(["log", "--oneline"]) | Cmd::new("head").arg("-5"))
    .timeout(Duration::from_secs(10))
    .retry(RetryPolicy::default())
    .run()?;

Trait Implementations§

Source§

impl BitOr for Cmd

Source§

fn bitor(self, rhs: Cmd) -> Cmd

Pipeline composition via |. Equivalent to Cmd::pipe.

Source§

type Output = Cmd

The resulting type after applying the | operator.
Source§

impl Clone for Cmd

Source§

fn clone(&self) -> Cmd

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Cmd

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Display for Cmd

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Renders the command (or pipeline) shell-style via CmdDisplay, respecting .secret().

Auto Trait Implementations§

§

impl Freeze for Cmd

§

impl !RefUnwindSafe for Cmd

§

impl Send for Cmd

§

impl Sync for Cmd

§

impl Unpin for Cmd

§

impl UnsafeUnpin for Cmd

§

impl !UnwindSafe for Cmd

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.