//! An implementation of asynchronous process management for Tokio.
//!
//! This module provides a [`Command`] struct that imitates the interface of the
//! [`std::process::Command`] type in the standard library, but provides asynchronous versions of
//! functions that create processes. These functions (`spawn`, `status`, `output` and their
//! variants) return "future aware" types that interoperate with Tokio. The asynchronous process
//! support is provided through signal handling on Unix and system APIs on Windows.
//!
//! [`std::process::Command`]: std::process::Command
//!
//! # Examples
//!
//! Here's an example program which will spawn `echo hello world` and then wait
//! for it complete.
//!
//! ```no_run
//! use tokio::process::Command;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // The usage is similar as with the standard library's `Command` type
//! let mut child = Command::new("echo")
//! .arg("hello")
//! .arg("world")
//! .spawn()
//! .expect("failed to spawn");
//!
//! // Await until the command completes
//! let status = child.wait().await?;
//! println!("the command exited with: {}", status);
//! Ok(())
//! }
//! ```
//!
//! Next, let's take a look at an example where we not only spawn `echo hello
//! world` but we also capture its output.
//!
//! ```no_run
//! use tokio::process::Command;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! // Like above, but use `output` which returns a future instead of
//! // immediately returning the `Child`.
//! let output = Command::new("echo").arg("hello").arg("world")
//! .output();
//!
//! let output = output.await?;
//!
//! assert!(output.status.success());
//! assert_eq!(output.stdout, b"hello world\n");
//! Ok(())
//! }
//! ```
//!
//! We can also read input line by line.
//!
//! ```no_run
//! use tokio::io::{BufReader, AsyncBufReadExt};
//! use tokio::process::Command;
//!
//! use std::process::Stdio;
//!
//! #[tokio::main]
//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
//! let mut cmd = Command::new("cat");
//!
//! // Specify that we want the command's standard output piped back to us.
//! // By default, standard input/output/error will be inherited from the
//! // current process (for example, this means that standard input will
//! // come from the keyboard and standard output/error will go directly to
//! // the terminal if this process is invoked from the command line).
//! cmd.stdout(Stdio::piped());
//!
//! let mut child = cmd.spawn()
//! .expect("failed to spawn command");
//!
//! let stdout = child.stdout.take()
//! .expect("child did not have a handle to stdout");
//!
//! let mut reader = BufReader::new(stdout).lines();
//!
//! // Ensure the child process is spawned in the runtime so it can
//! // make progress on its own while we await for any output.
//! tokio::spawn(async move {
//! let status = child.wait().await
//! .expect("child process encountered an error");
//!
//! println!("child status was: {}", status);
//! });
//!
//! while let Some(line) = reader.next_line().await? {
//! println!("Line: {}", line);
//! }
//!
//! Ok(())
//! }
//! ```
//!
//! # Caveats
//!
//! Similar to the behavior to the standard library, and unlike the futures
//! paradigm of dropping-implies-cancellation, a spawned process will, by
//! default, continue to execute even after the `Child` handle has been dropped.
//!
//! The [`Command::kill_on_drop`] method can be used to modify this behavior
//! and kill the child process if the `Child` wrapper is dropped before it
//! has exited.
//!
//! [`Command`]: crate::process::Command
#[path = "unix/mod.rs"]
#[cfg(unix)]
mod imp;
#[cfg(unix)]
pub(crate) mod unix {
pub(crate) use super::imp::*;
}
#[path = "windows.rs"]
#[cfg(windows)]
mod imp;
mod kill;
use crate::io::{AsyncRead, AsyncWrite, ReadBuf};
use crate::process::kill::Kill;
use std::ffi::OsStr;
use std::future::Future;
use std::io;
#[cfg(unix)]
use std::os::unix::process::CommandExt;
#[cfg(windows)]
use std::os::windows::process::CommandExt;
use std::path::Path;
use std::pin::Pin;
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
use std::task::Context;
use std::task::Poll;
/// This structure mimics the API of [`std::process::Command`] found in the standard library, but
/// replaces functions that create a process with an asynchronous variant. The main provided
/// asynchronous functions are [spawn](Command::spawn), [status](Command::status), and
/// [output](Command::output).
///
/// `Command` uses asynchronous versions of some `std` types (for example [`Child`]).
///
/// [`std::process::Command`]: std::process::Command
/// [`Child`]: struct@Child
#[derive(Debug)]
pub struct Command {
std: StdCommand,
kill_on_drop: bool,
}
pub(crate) struct SpawnedChild {
child: imp::Child,
stdin: Option<imp::ChildStdin>,
stdout: Option<imp::ChildStdout>,
stderr: Option<imp::ChildStderr>,
}
impl Command {
/// 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.
///
/// The search path to be used may be controlled by setting the
/// `PATH` environment variable on the Command,
/// but this has some implementation limitations on Windows
/// (see issue [rust-lang/rust#37519]).
///
/// # Examples
///
/// Basic usage:
///
/// ```no_run
/// use tokio::process::Command;
/// let command = Command::new("sh");
/// ```
///
/// [rust-lang/rust#37519]: https://github.com/rust-lang/rust/issues/37519
pub fn new<S: AsRef<OsStr>>(program: S) -> Command {
Self::from(StdCommand::new(program))
}