Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
procpilot
Subprocess runner for Rust. Typed errors, retry, timeout, stdin piping, pipelines, secret redaction, optional async.
What it does
RunErrorwithSpawn,NonZeroExit, andTimeoutvariants (captured stdout/stderr on the latter two).- Retry via
backon(exponential backoff + jitter) with a configurable predicate. .timeout()per attempt,.deadline()across all attempts.- Stdin from owned bytes (reusable across retries) or a boxed
Read(one-shot). - Stdout/stderr routing: capture, inherit, null, redirect to file.
Cmd::runhonors both;Cmd::spawnalways pipes stdout so the handle can expose it. .secret()replaces args with<secret>in error output and logs..spawn()returns aSpawnedProcesswithtake_stdin/take_stdout,Readimpls,kill,wait,wait_timeout, andspawn_and_collect_lines.- Pipelines via
.pipe()or|, executed with pipefail status precedence. Cmd: Clonefor base-plus-variants usage;impl Display for Cmd.- Async (
.run_async(),.spawn_async()) behind thetokiofeature.
Usage
[]
= "0.6"
For async (tokio) users:
[]
= { = "0.6", = ["tokio"] }
use Duration;
use ;
let output = new
.args
.in_dir
.env
.timeout
.run?;
# Ok::
For codebases that reach for procpilot's types frequently, a prelude is available:
use *;
let _: Cmd = new.stderr;
Reusing a base Cmd
Cmd is Clone, so you can build a base configuration once and branch off variants:
use Cmd;
let base = new.in_dir.env;
let status = base.clone.args.run?;
let log = base.clone.args.run?;
# Ok::
Error handling
use ;
match new.args.run
# ; Ok::
RunError is #[non_exhaustive]; include a wildcard arm. All variants carry a [CmdDisplay] that renders the command shell-style (with secret redaction if .secret() was set). NonZeroExit and Timeout include up to the last 128 KiB of stdout/stderr.
Retry
use ;
new
.args
.in_dir
.retry
.retry_when
.run?;
# Ok::
Deadline across retries
.timeout() bounds a single attempt; .deadline() bounds the whole operation (including retry backoff sleeps).
use ;
use ;
new
.args
.in_dir
.timeout
.deadline
.retry
.run?;
# Ok::
Inheriting stderr
Route the child's stderr to the parent's stderr (instead of capturing) with Redirection::Inherit. Useful when the child prompts the user or when live progress should be visible.
use ;
new
.args
.stderr
.run?;
# Ok::
Stdin
use Cmd;
let manifest = "apiVersion: v1\nkind: ConfigMap\n...";
new.args.stdin.run?;
# Ok::
Pipelines
Chain commands with [Cmd::pipe] or the | operator. Per-stage builders (arg, args, env, in_dir) target the rightmost stage; pipeline-level knobs (stdin, timeout, retry, stderr) apply to the pipeline.
use Cmd;
let out = new.args
.pipe
.pipe
.run?;
// Same, with `|`:
let out =
.run?;
# Ok::
Failure status follows pipefail semantics: any non-success trumps success; the rightmost non-success wins. All stages' stderr is captured and concatenated (capture mode) or routed identically (inherit/null/file).
Streaming (spawned processes)
For long-lived or bidirectional processes, use [Cmd::spawn] instead of .run(). SpawnedProcess exposes ownership of stdin/stdout pipes; lifecycle methods (wait, kill) take &self so the handle can be shared across threads.
use ;
use thread;
use Cmd;
// `git cat-file --batch` pattern: write requests on one thread, read
// responses on another.
let proc = new
.args
.in_dir
.spawn?;
let mut stdin = proc.take_stdin.expect;
let stdout = proc.take_stdout.expect;
spawn;
let mut reader = new;
let mut header = Stringnew;
reader.read_line?;
// ... parse headers + binary content ...
let _ = proc.wait;
# Ok::
Line-at-a-time variant:
use Cmd;
new
.args
.spawn_and_collect_lines?;
# Ok::
Secret redaction
use Cmd;
new.args.secret.run?;
// Error messages show `docker <secret>` instead of the token.
# Ok::
Async (tokio)
Enable the tokio feature to use .run_async() and .spawn_async() from inside a tokio runtime. The sync .run() would block the executor thread.
[]
= { = "0.6", = ["tokio"] }
use Cmd;
let out = new
.args
.in_dir
.run_async
.await?;
# Ok::
Run commands concurrently:
use Cmd;
let branch = new.args.in_dir.run_async;
let remote = new.args.in_dir.run_async;
let status = new.args.in_dir.run_async;
let = try_join!?;
# Ok::
.spawn_async() returns an AsyncSpawnedProcess for streaming:
use Cmd;
use ;
let mut proc = new.args.spawn_async.await?;
let stdout = proc.take_stdout.expect;
let mut lines = new.lines;
while let Ok = lines.next_line.await
proc.wait.await?;
# Ok::
Cancellation via tokio::select!:
select!
# Ok::
Pipelines:
let out =
.run_async
.await?;
# Ok::
All builder knobs (arg, args, env, envs, in_dir, stdin, stderr, timeout, deadline, retry, retry_when, secret, pipe, |) work identically on the async path.
Not yet on the async path:
impl AsyncRead for AsyncSpawnedProcess(usetake_stdout()).&selflifecycle methods — usetokio::select!to racewaitagainstkill.
License
Licensed under either Apache-2.0 or MIT at your option.