Crate tokio_process
source ·Expand description
An implementation of asynchronous process management for Tokio.
This crate provides a CommandExt
trait to enhance the functionality of the
Command
type in the standard library. The three methods provided by this
trait mirror the “spawning” methods in the standard library. The
CommandExt
trait in this crate, though, returns “future aware” types that
interoperate with Tokio. The asynchronous process support is provided
through signal handling on Unix and system APIs on Windows.
Examples
Here’s an example program which will spawn echo hello world
and then wait
for it using an event loop.
extern crate futures;
extern crate tokio;
extern crate tokio_process;
use std::process::Command;
use futures::Future;
use tokio_process::CommandExt;
fn main() {
// Use the standard library's `Command` type to build a process and
// then execute it via the `CommandExt` trait.
let child = Command::new("echo").arg("hello").arg("world")
.spawn_async();
// Make sure our child succeeded in spawning and process the result
let future = child.expect("failed to spawn")
.map(|status| println!("exit status: {}", status))
.map_err(|e| panic!("failed to wait for exit: {}", e));
// Send the future to the tokio runtime for execution
tokio::run(future)
}
Next, let’s take a look at an example where we not only spawn echo hello world
but we also capture its output.
extern crate futures;
extern crate tokio;
extern crate tokio_process;
use std::process::Command;
use futures::Future;
use tokio_process::CommandExt;
fn main() {
// Like above, but use `output_async` which returns a future instead of
// immediately returning the `Child`.
let output = Command::new("echo").arg("hello").arg("world")
.output_async();
let future = output.map_err(|e| panic!("failed to collect output: {}", e))
.map(|output| {
assert!(output.status.success());
assert_eq!(output.stdout, b"hello world\n");
});
tokio::run(future);
}
We can also read input line by line.
extern crate futures;
extern crate tokio;
extern crate tokio_process;
extern crate tokio_io;
use std::io;
use std::process::{Command, Stdio};
use futures::{Future, Stream};
use tokio_process::{CommandExt, Child};
fn print_lines(mut cat: Child) -> Box<Future<Item = (), Error = ()> + Send + 'static> {
let stdout = cat.stdout().take().unwrap();
let reader = io::BufReader::new(stdout);
let lines = tokio_io::io::lines(reader);
let cycle = lines.for_each(|l| {
println!("Line: {}", l);
Ok(())
});
let future = cycle.join(cat)
.map(|_| ())
.map_err(|e| panic!("{}", e));
Box::new(future)
}
fn main() {
let mut cmd = Command::new("cat");
cmd.stdout(Stdio::piped());
let future = print_lines(cmd.spawn_async().expect("failed to spawn command"));
tokio::run(future);
}
Caveats
While similar to the standard library, this crate’s Child
type differs
importantly in the behavior of drop
. In the standard library, a child
process will continue running after the instance of std::process::Child
is dropped. In this crate, however, because tokio_process::Child
is a
future of the child’s ExitStatus
, a child process is terminated if
tokio_process::Child
is dropped. The behavior of the standard library can
be regained with the Child::forget
method.
Structs
CommandExt::output_async
method.CommandExt::status_async
method.Child::wait_with_output
method.Traits
Command
type in the standard
library.