Command
The std::process::Command struct is a process builder that configures every aspect of a child process before launching it: the executable path, individual or batched arguments, working directory, environment variables, and standard I/O descriptors.
Builder Configuration Methods
| Method | Signature Summary | Description |
|---|---|---|
Command::new(program) |
new<S: AsRef<OsStr>>(program: S) -> Command |
Creates a new Command for program, resolved via PATH if not a path. |
.arg(arg) |
arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command |
Appends a single command-line argument. |
.args(iter) |
args<I, S>(&mut self, args: I) -> &mut Command |
Appends multiple command-line arguments from an iterator. |
.current_dir(dir) |
current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Command |
Sets the working directory solely for the child process. |
.env(key, val) |
env<K, V>(&mut self, key: K, val: V) -> &mut Command |
Inserts or overrides an environment variable for the child. |
.envs(iter) |
envs<I, K, V>(&mut self, vars: I) -> &mut Command |
Inserts or overrides multiple (key, val) pairs. |
.env_remove(key) |
env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Command |
Removes an inherited environment variable from the child. |
.env_clear() |
env_clear(&mut self) -> &mut Command |
Clears all inherited environment variables, starting from an empty environment. |
Passing Arguments Correctly: .arg() vs Combined Strings
Each distinct flag and option value must be passed as a separate argument via .arg() or .args(). Passing "--out-dir /tmp/build" as a single .arg() passes a single string containing a space rather than two arguments.
use std::env;
use std::ffi::OsStr;
use std::process::Command;
fn main() {
let mut cmd = Command::new("rustc");
cmd.arg("--edition=2024")
.args(["--crate-type", "lib"])
.current_dir(env::temp_dir())
.env("RUST_BACKTRACE", "1")
.env_remove("RUSTFLAGS");
// Inspect configured command state before execution
println!("Program: {:?}", cmd.get_program());
let collected_args: Vec<&OsStr> = cmd.get_args().collect();
println!("Args: {:?}", collected_args);
println!("Has CWD: {}", cmd.get_current_dir().is_some());
}
Program: "rustc"
Args: ["--edition=2024", "--crate-type", "lib"]
Has CWD: true
Constructing a Clean Hermetic Environment with .env_clear()
By default, a Command inherits all environment variables from the parent process. Security-sensitive tools, build systems, and test runners often call .env_clear() to strip inherited secrets (such as API tokens or LD_PRELOAD) and whitelist only required variables:
use std::env;
use std::io;
use std::process::Command;
fn main() -> io::Result<()> {
let mut cmd = Command::new("rustc");
cmd.arg("--version")
.env_clear()
.env("CustomKey", "HermeticValue");
// Preserve PATH so the OS can locate `rustc` and its linker/libraries
if let Some(path) = env::var_os("PATH") {
cmd.env("PATH", path);
}
if let Some(sysroot) = env::var_os("SystemRoot") {
cmd.env("SystemRoot", sysroot); // Required on Windows
}
let status = cmd.output()?.status;
println!("Hermetic child succeeded: {}", status.success());
Ok(())
}
Hermetic child succeeded: true
Reusing a Command Builder
Because .spawn(), .output(), and .status() take &mut self rather than consuming self by value, a configured Command can be executed repeatedly in a loop or augmented with additional .arg() calls between runs.