subprocess/
lib.rs

1//! Execution of and interaction with external processes and pipelines.
2//!
3//! The entry points to the crate are the [`Popen`] struct and the [`Exec`] builder.  `Popen`
4//! is the interface to a running child process, inspired by Python's [`subprocess.Popen`].
5//! `Exec` provides a builder-pattern API with convenient methods for streaming and capturing
6//! of output, as well as combining `Popen` instances into pipelines.
7//!
8//! Compared to `std::process`, the crate provides these additional features:
9//!
10//! * The *communicate* [family of methods](Popen::communicate_start) for deadlock-free
11//!   capturing of subprocess output/error, while simultaneously feeding data to its standard
12//!   input.  Capturing supports optional timeout and read size limit.
13//!
14//! * Connecting multiple commands into OS-level [pipelines](Pipeline).
15//!
16//! * Flexible [redirection options](Redirection), such as connecting standard streams to
17//!   arbitrary [open files](Redirection::File), or [merging](Redirection::Merge) output
18//!   streams like shell's `2>&1` and `1>&2` operators.
19//!
20//! * Non-blocking and timeout methods to wait on the process: [`poll`](Popen::poll),
21//!   [`wait`](Popen::wait), and [`wait_timeout`](Popen::wait_timeout).
22//!
23//! # Examples
24//!
25//! Communicate with a process and optionally terminate it:
26//!
27//! ```
28//! # use subprocess::*;
29//! # fn dummy() -> Result<()> {
30//! let mut p = Popen::create(&["ps", "x"], PopenConfig {
31//!     stdout: Redirection::Pipe, ..Default::default()
32//! })?;
33//!
34//! // Obtain the output from the standard streams.
35//! let (out, err) = p.communicate(None)?;
36//!
37//! if let Some(exit_status) = p.poll() {
38//!     // the process has finished
39//! } else {
40//!     // it is still running, terminate it
41//!     p.terminate()?;
42//! }
43//! # Ok(())
44//! # }
45//! ```
46//!
47//! Use the [`Exec`] builder to execute a pipeline of commands and capture the output:
48//!
49//! ```no_run
50//! # use subprocess::*;
51//! # fn dummy() -> Result<()> {
52//! let dir_checksum = {
53//!     Exec::shell("find . -type f") | Exec::cmd("sort") | Exec::cmd("sha1sum")
54//! }.capture()?.stdout_str();
55//! # Ok(())
56//! # }
57//! ```
58//!
59//! [`subprocess.Popen`]: https://docs.python.org/3/library/subprocess.html#subprocess.Popen
60
61#![warn(missing_debug_implementations, missing_docs)]
62#![allow(clippy::type_complexity)]
63
64mod builder;
65mod communicate;
66mod popen;
67
68#[cfg(unix)]
69mod posix;
70
71#[cfg(windows)]
72mod win32;
73
74mod os_common;
75
76pub use builder::{CaptureData, Exec, ExecExt, NullFile, Pipeline};
77pub use communicate::{CommunicateError, Communicator};
78pub use os_common::ExitStatus;
79pub use popen::{Popen, PopenConfig, PopenError, Redirection, Result, make_pipe};
80
81/// Subprocess extensions for Unix platforms.
82#[cfg(unix)]
83pub mod unix {
84    pub use super::popen::os_ext::*;
85}
86
87/// Subprocess extensions for Windows platforms.
88#[cfg(windows)]
89pub mod windows {
90    pub use super::builder::windows::*;
91}
92
93#[cfg(test)]
94mod tests {
95    mod builder;
96    mod common;
97    #[cfg(unix)]
98    mod posix;
99    #[cfg(windows)]
100    mod win32;
101}