Skip to main content

Pipeline

Struct Pipeline 

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

A builder for pipelines of subprocesses connected via pipes.

A pipeline is a sequence of two or more Exec commands connected via pipes. Just like in a Unix shell pipeline, each command receives standard input from the previous command, and passes standard output to the next command. Optionally, the standard input of the first command can be provided from the outside, and the output of the last command can be captured.

In most cases you do not need to create Pipeline instances directly; instead, combine Exec instances using the | operator which produces Pipeline.

§Examples

Execute a pipeline and return the exit status of the last command:

let exit_status =
  (Exec::shell("ls *.bak") | Exec::cmd("xargs").arg("rm")).join()?;

Capture the pipeline’s output:

let dir_checksum = {
    Exec::shell("find . -type f") | Exec::cmd("sort") | Exec::cmd("sha1sum")
}.capture()?.stdout_str();

Implementations§

Source§

impl Pipeline

Source

pub fn new() -> Pipeline

Creates a new empty pipeline.

Use pipe to add commands to the pipeline, or the | operator to combine Exec instances.

An empty pipeline’s join() returns success and capture() returns empty output. A single-command pipeline behaves like the command run on its own.

Source

pub fn pipe(self, cmd: Exec) -> Pipeline

Appends a command to the pipeline.

This is the builder-style equivalent of the | operator.

§Example
let output = Pipeline::new()
    .pipe(Exec::cmd("echo").arg("hello world"))
    .pipe(Exec::cmd("wc").arg("-w"))
    .capture()?
    .stdout_str();
Source

pub fn stdin<T>(self, stdin: T) -> Pipeline
where InputRedirection: FromSource<T>,

Specifies the source for the standard input of the first command in the pipeline.

The source can be:

  • a Redirection;
  • a File, which is a shorthand for Redirection::File(file);
  • a Vec<u8>, &str, &[u8], Box<[u8]>, or [u8; N], which will set up a Redirection::Pipe for stdin, feeding that data into the standard input of the subprocess;
  • an InputData, which also sets up a pipe, but wraps any reader and feeds its content to the standard input of the subprocess. Use InputData::from_bytes for in-memory byte containers not covered by the above, like bytes::Bytes or memmap2::Mmap. Use InputData::from_reader for a custom Read that generates or transforms data.

If the child exits before consuming all input, the BrokenPipe error is silently ignored. Use the exit status and output to check if the child processed the input correctly.

Source

pub fn stdout<T>(self, stdout: T) -> Pipeline

Specifies the sink for the standard output of the last command in the pipeline.

The sink can be:

  • a Redirection;
  • a File, which is a shorthand for Redirection::File(file).
Source

pub fn stderr_all<T>(self, stderr: T) -> Pipeline

Specifies the sink for the standard error of all commands in the pipeline.

Unlike stdout(), which only affects the last command in the pipeline, this affects all commands. The difference is because standard output is piped from one command to the next, so only the output of the last command is “free”. In contrast, the standard errors are not connected to each other and can be configured en masse.

The sink can be:

  • a Redirection;
  • a File, which is a shorthand for Redirection::File(file).

All Redirection variants are meaningful:

  • Redirection::None - inherit from the parent (the default)
  • Redirection::Pipe - funnel stderr of all commands into stderr obtained with capture() or communicate()
  • Redirection::Merge - redirect stderr to stdout, like 2>&1 for each command
  • Redirection::File(f) - redirect to a file
  • Redirection::Null - suppress stderr

Note that this differs from the shell’s cmd1 | cmd2 2>file, which only redirects stderr of the last command. This method is equivalent to (cmd1 | cmd2) 2>file, but without the overhead of a subshell.

If you pass Redirection::Pipe, the shared stderr read end will be available via Job::stderr.

Source

pub fn checked(self) -> Pipeline

If called, join and capture will return an error if the last command in the pipeline exits with a non-zero status.

Source

pub fn cwd(self, dir: impl AsRef<Path>) -> Pipeline

Specifies the current working directory for all commands in the pipeline.

If unspecified, the current working directory is inherited from the parent.

Source

pub fn detached(self) -> Pipeline

Specifies that the pipeline processes are initially detached.

A detached pipeline means that we will not wait for the processes to finish when the objects that own them go out of scope.

Source

pub fn start(self) -> Result<Job>

Starts all commands in the pipeline and returns a Job with the running processes and their pipe ends.

If some command fails to start, the remaining commands will not be started, and the appropriate error will be returned. The commands that have already started will be waited to finish (but will probably exit immediately due to missing output), except for the ones for which detached() was called. This is equivalent to what the shell does.

Source

pub fn join(self) -> Result<ExitStatus>

Starts the pipeline, waits for it to finish, and returns the exit status of the last command.

Source

pub fn stream_stdout(self) -> Result<impl Read>

Starts the pipeline and returns a value implementing the Read trait that reads from the standard output of the last command.

This will automatically set up stdout(Redirection::Pipe), so it is not necessary to do that beforehand.

When the trait object is dropped, it will wait for the pipeline to finish. If this is undesirable, use detached().

§Panics

Panics if input data was specified with stdin. Use capture or communicate to both feed input and read output.

Source

pub fn stream_stderr_all(self) -> Result<impl Read>

Starts the pipeline and returns a value implementing the Read trait that reads from the standard error of all commands in the pipeline.

This will automatically set up stderr_all(Redirection::Pipe), so it is not necessary to do that beforehand.

Note that this redirects stderr of all commands in the pipeline, not just the last one. This differs from the shell’s cmd1 | cmd2 2>file, which only redirects stderr of the last command. This method is equivalent to (cmd1 | cmd2) 2>file, but without the overhead of a subshell.

When the trait object is dropped, it will wait for the pipeline to finish. If this is undesirable, use detached().

§Panics

Panics if input data was specified with stdin. Use capture or communicate to both feed input and read output.

Source

pub fn stream_stdin(self) -> Result<impl Write>

Starts the pipeline and returns a value implementing the Write trait that writes to the standard input of the first command.

This will automatically set up stdin(Redirection::Pipe), so it is not necessary to do that beforehand.

When the trait object is dropped, it will wait for the pipeline to finish. If this is undesirable, use detached().

§Panics

Panics if input data was specified with stdin.

Source

pub fn communicate(self) -> Result<Communicator>

Starts the pipeline and returns a Communicator handle.

Unless already configured, stdout and stderr are redirected to pipes. If you need different redirection (e.g. stderr_all(Merge)), set it up before calling this method and it will be preserved.

Compared to capture(), this offers more choice in how communication is performed, such as read size limit and timeout. Unlike capture(), this method doesn’t wait for the pipeline to finish, effectively detaching it.

Source

pub fn capture(self) -> Result<Capture>

Starts the pipeline, collects its output, and waits for it to finish.

The return value provides the standard output and standard error as bytes or optionally strings, as well as the exit status.

Unless already configured, stdout and stderr are redirected to pipes so they can be captured. If you need different redirection (e.g. stderr_all(Merge)), set it up before calling this method and it will be preserved.

This method waits for the pipeline to finish, rather than simply waiting for its standard streams to close. If this is undesirable, use detached().

Trait Implementations§

Source§

impl BitOr<Exec> for Pipeline

Source§

fn bitor(self, rhs: Exec) -> Pipeline

Append a command to the pipeline and return a new pipeline.

Source§

type Output = Pipeline

The resulting type after applying the | operator.
Source§

impl BitOr for Pipeline

Source§

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

Append the commands from rhs to this pipeline.

Other pipeline-level settings (cwd, stdout, etc.) from rhs are dropped - only its commands are taken.

Source§

type Output = Pipeline

The resulting type after applying the | operator.
Source§

impl Debug for Pipeline

Source§

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

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

impl Default for Pipeline

Source§

fn default() -> Pipeline

Returns the “default value” for a type. Read more
Source§

impl FromIterator<Exec> for Pipeline

Source§

fn from_iter<I: IntoIterator<Item = Exec>>(iter: I) -> Self

Creates a pipeline from an iterator of commands.

The iterator may yield any number of commands, including zero or one. An empty pipeline returns success on join() and empty output on capture(). A single-command pipeline behaves like running that command directly.

§Example
use subprocess::{Exec, Pipeline};

let commands = vec![
  Exec::shell("echo tset"),
  Exec::shell("tr '[:lower:]' '[:upper:]'"),
  Exec::shell("rev")
];

let pipeline: Pipeline = commands.into_iter().collect();
let output = pipeline.capture().unwrap().stdout_str();
assert_eq!(output, "TEST\n");
Source§

impl PipelineExt for Pipeline

Source§

fn setpgid(self) -> Pipeline

Put all pipeline processes into a shared process group. Read more

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 = 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.