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