Skip to main content

Command

Struct Command 

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

A builder for spawning a process.

Implementations§

Source§

impl Command

Source

pub fn new<S: AsRef<OsStr>>(program: S) -> Self

Constructs a new Command for launching the program at path program, with the following default configuration:

  • No arguments to the program
  • Inherit the current process’s environment
  • Inherit the current process’s working directory
  • Inherit stdin/stdout/stderr for spawn or status, but create pipes for output

Builder methods are provided to change these defaults and otherwise configure the process.

If program is not an absolute path, the PATH will be searched in an OS-defined way.

§Examples

Basic usage:

use reverie_process::Command;
let command = Command::new("sh");
Source

pub fn program<S: AsRef<OsStr>>(&mut self, program: S) -> &mut Self

Sets the path to the program. This can be used to override what was already set in Command::new.

NOTE: This also changes argument 0 to match program.

Source

pub fn arg0<S: AsRef<OsStr>>(&mut self, arg0: S) -> &mut Self

Explicitly sets the first argument. By default, this is the same as the program path and is what you want in most cases.

Source

pub fn get_arg0(&self) -> &OsStr

Gets the first argument. Unless Command::arg0 was used, this returns the same string as Command::get_program.

Source

pub fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Self

Adds an argument to pass to the program.

Only one argument can be passed per use. So instead of:

reverie_process::Command::new("sh").arg("-C /path/to/repo");

usage would be:

reverie_process::Command::new("sh")
    .arg("-C")
    .arg("/path/to/repo");

To pass multiple arguments see args.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").arg("-l").arg("-a");
Source

pub fn args<I, S>(&mut self, args: I) -> &mut Self
where I: IntoIterator<Item = S>, S: AsRef<OsStr>,

Adds multiple arguments to pass to the program.

To pass a single argument see arg.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").args(&["-l", "-a"]);
Source

pub fn get_args(&self) -> impl Iterator<Item = &OsStr>

Returns an iterator of the arguments that will be passed to the program.

This does not include the program name itself. It only includes the arguments specified with Command::arg and Command::args.

Source

pub fn prepend_args<I, S>(&mut self, args: I) -> &mut Self
where I: IntoIterator<Item = S>, S: AsRef<OsStr>,

Prepends arguments to the beginning of the command. Note that arguments are prepended after arg0, but before the rest of the arguments.

Source

pub fn env<K, V>(&mut self, key: K, val: V) -> &mut Self
where K: AsRef<OsStr>, V: AsRef<OsStr>,

Inserts or updates an environment variable mapping.

Note that environment variable names are case-insensitive (but case-preserving) on Windows, and case-sensitive on all other platforms.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").env("PATH", "/bin");
Source

pub fn envs<I, K, V>(&mut self, vars: I) -> &mut Self
where I: IntoIterator<Item = (K, V)>, K: AsRef<OsStr>, V: AsRef<OsStr>,

Adds or updates multiple environment variable mappings.

§Examples

Basic usage:

use std::collections::HashMap;
use std::env;

use reverie_process::Command;
use reverie_process::Stdio;

let filtered_env: HashMap<String, String> = env::vars()
    .filter(|&(ref k, _)| k == "TERM" || k == "TZ" || k == "LANG" || k == "PATH")
    .collect();

let command = Command::new("printenv")
    .stdin(Stdio::null())
    .stdout(Stdio::inherit())
    .env_clear()
    .envs(&filtered_env);
Source

pub fn env_remove<K: AsRef<OsStr>>(&mut self, key: K) -> &mut Self

Removes an environment variable mapping.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").env_remove("PATH");
Source

pub fn env_clear(&mut self) -> &mut Self

Clears the entire environment map for the child process.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").env_clear();
Source

pub fn current_dir<P: AsRef<Path>>(&mut self, dir: P) -> &mut Self

Sets the working directory for the child process.

§Interaction with chroot

The working directory is set after the chroot is performed (if a chroot directory is specified). Thus, the path given is relative to the chroot directory. Otherwise, if no chroot directory is specified, the working directory is relative to the current working directory of the parent process at the time the child process is spawned.

§Platform-specific behavior

If the program path is relative (e.g., "./script.sh"), it’s ambiguous whether it should be interpreted relative to the parent’s working directory or relative to current_dir. The behavior in this case is platform specific and unstable, and it’s recommended to use canonicalize to get an absolute program path instead.

§Examples

Basic usage:

use reverie_process::Command;

let command = Command::new("ls").current_dir("/bin");
Source

pub fn stdin<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self

Sets configuration for the child process’s standard input (stdin) handle.

Defaults to Stdio::inherit when used with spawn or status, and defaults to Stdio::piped when used with output.

§Examples

Basic usage:

use reverie_process::Command;
use reverie_process::Stdio;

let command = Command::new("ls").stdin(Stdio::null());
Source

pub fn stdout<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self

Sets configuration for the child process’s standard output (stdout) handle.

Defaults to Stdio::inherit when used with spawn or status, and defaults to Stdio::piped when used with output.

§Examples

Basic usage:

use reverie_process::Command;
use reverie_process::Stdio;

let command = Command::new("ls").stdout(Stdio::null());
Source

pub fn stderr<T: Into<Stdio>>(&mut self, cfg: T) -> &mut Self

Sets configuration for the child process’s standard error (stderr) handle.

Defaults to Stdio::inherit when used with spawn or status, and defaults to Stdio::piped when used with output.

§Examples

Basic usage:

use reverie_process::Command;
use reverie_process::Stdio;

let command = Command::new("ls").stderr(Stdio::null());
Source

pub fn chroot<P: AsRef<Path>>(&mut self, chroot: P) -> &mut Self

Changes the root directory of the calling process to the specified path. This directory will be inherited by all child processes of the calling process.

Note that changing the root directory may cause the program to not be found. As such, the program path should be relative to this directory.

Source

pub fn unshare(&mut self, namespace: Namespace) -> &mut Self

Unshares parts of the process execution context that are normally shared with the parent process. This is useful for executing the child process in a new namespace.

Source

pub unsafe fn pre_exec<F>(&mut self, f: F) -> &mut Self
where F: FnMut() -> Result<(), Errno> + Send + Sync + 'static,

Schedules a closure to be run just before the exec function is invoked.

The closure is allowed to return an I/O error whose OS error code will be communicated back to the parent and returned as an error from when the spawn was requested.

Multiple closures can be registered and they will be called in order of their registration. If a closure returns Err then no further closures will be called and the spawn operation will immediately return with a failure.

§Safety

This closure will be run in the context of the child process after a fork. This primarily means that any modifications made to memory on behalf of this closure will not be visible to the parent process. This is often a very constrained environment where normal operations like malloc or acquiring a mutex are not guaranteed to work (due to other threads perhaps still running when the fork was run).

This also means that all resources such as file descriptors and memory-mapped regions got duplicated. It is your responsibility to make sure that the closure does not violate library invariants by making invalid use of these duplicates.

When this closure is run, aspects such as the stdio file descriptors and working directory have successfully been changed, so output to these locations may not appear where intended.

Source

pub fn get_program(&self) -> &OsStr

Returns the path to the program that was given to Command::new.

§Examples
use reverie_process::Command;

let cmd = Command::new("echo");
assert_eq!(cmd.get_program(), "echo");
Source

pub fn get_current_dir(&self) -> Option<&Path>

Returns the working directory for the child process.

This returns None if the working directory will not be changed.

Source

pub fn get_envs(&self) -> impl Iterator<Item = (&OsStr, Option<&OsStr>)>

Returns an iterator of the environment variables that will be set when the process is spawned. Note that this does not include any environment variables inherited from the parent process.

Source

pub fn get_captured_envs(&self) -> BTreeMap<OsString, OsString>

Returns a mapping of all environment variables that the new child process will inherit.

Source

pub fn get_env<K: AsRef<OsStr>>(&self, env: K) -> Option<Cow<'_, OsStr>>

Gets an environment variable. If the child process is to inherit this environment variable from the current process, then this returns the current process’s environment variable unless it is to be overridden.

Source

pub fn map_uid(&mut self, inside_uid: uid_t, outside_uid: uid_t) -> &mut Self

Maps one user ID to another.

Implies Namespace::USER.

§Example

This is can be used to gain CAP_SYS_ADMIN privileges in the user namespace by mapping the root user inside the container to the current user outside of the container.

use reverie_process::Command;

let command = Command::new("ls").map_uid(1, unsafe { libc::getuid() });
§Implementation

This modifies /proc/{pid}/uid_map where {pid} is the PID of the child process. See user_namespaces(7) for more details.

Source

pub fn map_uid_range( &mut self, starting_inside_uid: uid_t, starting_outside_uid: uid_t, count: u32, ) -> &mut Self

Maps potentially many user IDs inside the new user namespace to user IDs outside of the user namespace.

Implies Namespace::USER.

§Implementation

This modifies /proc/{pid}/uid_map where {pid} is the PID of the child process. See user_namespaces(7) for more details.

Source

pub fn map_root(&mut self) -> &mut Self

Convience function for mapping root (inside the container) to the current user ID (outside the container). This is useful for gaining new capabilities inside the container, such as being able to mount file systems.

Implies Namespace::USER.

This is the same as:

use reverie_process::Command;

let command = Command::new("ls")
    .map_uid(0, unsafe { libc::geteuid() })
    .map_gid(0, unsafe { libc::getegid() });
Source

pub fn map_gid(&mut self, inside_gid: gid_t, outside_gid: gid_t) -> &mut Self

Maps one group ID to another.

Implies Namespace::USER.

§Implementation

This modifies /proc/{pid}/gid_map where {pid} is the PID of the child process. See user_namespaces(7) for more details.

Source

pub fn map_gid_range( &mut self, starting_inside_gid: gid_t, starting_outside_gid: gid_t, count: u32, ) -> &mut Self

Maps potentially many group IDs inside the new user namespace to group IDs outside of the user namespace.

Implies Namespace::USER.

§Implementation

This modifies /proc/{pid}/gid_map where {pid} is the PID of the child process. See user_namespaces(7) for more details.

Source

pub fn hostname<S: Into<OsString>>(&mut self, hostname: S) -> &mut Self

Sets the hostname of the container.

Implies Namespace::UTS, which requires CAP_SYS_ADMIN.

use reverie_process::Command;

let command = Command::new("cat")
    .arg("/proc/sys/kernel/hostname")
    .map_root()
    .hostname("foobar.local");
Source

pub fn domainname<S: Into<OsString>>(&mut self, domainname: S) -> &mut Self

Sets the domain name of the container.

Implies Namespace::UTS, which requires CAP_SYS_ADMIN.

§Example
use reverie_process::Command;

let command = Command::new("cat")
    .arg("/proc/sys/kernel/domainname")
    .map_root()
    .domainname("foobar");
Source

pub fn get_hostname(&self) -> Option<&OsStr>

Gets the hostname of the container.

Source

pub fn get_domainname(&self) -> Option<&OsStr>

Gets the domainname of the container.

Source

pub fn mount(&mut self, mount: Mount) -> &mut Self

Adds a file system to be mounted. Note that these are mounted in the same order as given.

Implies Namespace::MOUNT. Note that Namespace::USER should also have been set and map_uid should have been called in order to gain the privileges required to mount.

Source

pub fn mounts<I>(&mut self, mounts: I) -> &mut Self
where I: IntoIterator<Item = Mount>,

Adds multiple mounts.

Source

pub fn local_networking_only(&mut self) -> &mut Self

Sets up the container to have local networking only. This will prevent any network communication to the outside world.

Implies Namespace::NETWORK and Namespace::MOUNT.

This also causes a fresh /sys to be mounted to avoid seeing the host network interfaces in /sys/class/net.

Source

pub fn seccomp(&mut self, filter: Filter) -> &mut Self

Sets the seccomp filter. The filter is loaded immediately before execve and after all pre_exec callbacks have been executed. Thus, you will still be able to call filtered syscalls from pre_exec callbacks.

Source

pub fn seccomp_notify(&mut self) -> &mut Self

Indicates that we want to listen for seccomp events using seccomp_unotify(2).

If this is set, the seccomp listener file descriptor will be accessible via the Child.

Source

pub fn pty(&mut self, child: PtyChild) -> &mut Self

Sets the controlling pseudoterminal for the child process).

In the child process, this has the effect of:

  1. Creating a new session (with setsid()).
  2. Using an ioctl to set the controlling terminal.
  3. Setting this file descriptor as the stdio streams.

NOTE: Since this modifies the stdio streams, calling this will reset Self::stdin, Self::stdout, and Self::stderr back to Stdio::inherit().

Source

pub fn find_program(&self) -> Result<PathBuf>

Finds the path to the program.

Source§

impl Command

Source

pub async fn status(&mut self) -> Result<ExitStatus>

Executes the command, waiting for it to finish and collecting its exit status.

Source

pub async fn output(&mut self) -> Result<Output>

Executes the command, waiting for it to finish while collecting its stdout and stderr into buffers.

Source§

impl Command

Source

pub fn spawn(&mut self) -> Result<Child, Error>

Executes the command as a child process, returning a handle to it.

By default, stdin, stdout and stderr are inherited from the parent.

Source

pub fn spawn_with<F>(&mut self, onfail: F) -> Result<Child, Error>
where F: FnMut(Error) -> i32,

Spawn the child with helper functions. The onfail callback runs in the child process if an error occurs during execution of the process. The wait function can be used to wait for the child to fully start up and to transform it into another type.

Source§

impl Command

Source

pub fn from_std_lossy(cmd: &Command) -> Command

Converts std::process::Command into Command. Note that this is a very basic and lossy conversion.

This only preserves the

  • program path,
  • arguments,
  • environment variables,
  • and working directory.
§Caveats

Since std::process::Command is rather opaque and doesn’t provide access to all fields, this will not preserve:

  • stdio handles,
  • env_clear,
  • any pre_exec callbacks,
  • arg0 (if not the same as program),
  • uid, gid, or groups.
Source

pub fn try_into_std(self) -> Result<Command>

Converts this command to std::process::Command.

This fails if the command contains container configuration that cannot be represented by std::process::Command, rather than silently discarding that configuration. This includes namespaces, mounts, seccomp filters, pseudoterminals, and CPU affinity.

Source

pub fn into_std_lossy(self) -> Command

Converts this command to std::process::Command, refusing to discard any container configuration.

This compatibility shim preserves the former return type for callers whose commands are representable. It panics instead of silently losing unsupported configuration. New callers should use Self::try_into_std to handle that refusal explicitly.

Auto Trait Implementations§

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> 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, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.