14 个版本
0.3.0-alpha.2 | 2019 年 8 月 19 日 |
---|---|
0.2.5 | 2020 年 2 月 5 日 |
0.2.4 | 2019 年 6 月 22 日 |
0.2.3 | 2018 年 11 月 2 日 |
0.1.0 | 2016 年 9 月 10 日 |
#248 in #asynchronous
4,964 每月下载量
在 少于 17 crates 中使用
575KB
10K SLoC
tokio-process
为 Tokio 实现的进程管理
许可证
本项目采用 MIT 许可证。
贡献
除非您明确表示,否则您提交给 Tokio 的任何有意包含的贡献都将按 MIT 许可证许可,不附加任何额外条款或条件。
lib.rs
:
为 Tokio 实现异步进程管理。
该包提供了一个 Command 结构体,该结构体模仿了标准库中 std::process::Command
类型的接口,但提供了创建进程的函数的异步版本。这些函数(spawn
、status
、output
及其变体)返回与 Tokio 交互的 "future aware" 类型。异步进程支持通过 Unix 的信号处理和 Windows 的系统 API 提供。
示例
以下是一个示例程序,它会启动 echo hello world
并等待其完成。
#![feature(async_await)]
use tokio_process::Command;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// The usage is the same as with the standard library's `Command` type, however the value
// returned from `spawn` is a `Result` containing a `Future`.
let child = Command::new("echo").arg("hello").arg("world")
.spawn();
// Make sure our child succeeded in spawning and process the result
let future = child.expect("failed to spawn");
// Await until the future (and the command) completes
let status = future.await?;
println!("the command exited with: {}", status);
Ok(())
}
接下来,让我们看看一个示例,我们不仅启动 echo hello world
,还捕获其输出。
#![feature(async_await)]
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(())
}
我们还可以逐行读取输入。
#![feature(async_await)]
use futures_util::stream::StreamExt;
use std::process::{Stdio};
use tokio::codec::{FramedRead, LinesCodec};
use tokio_process::Command;
#[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 = FramedRead::new(stdout, LinesCodec::new());
// 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 {
let status = child.await
.expect("child process encountered an error");
println!("child status was: {}", status);
});
while let Some(line) = reader.next().await {
println!("Line: {}", line?);
}
Ok(())
}
注意事项
虽然与标准库类似,但这个crate中的Child
类型在drop
行为上有重要区别。在标准库中,当std::process::Child
实例被丢弃后,子进程将继续运行。然而,在这个crate中,由于tokio_process::Child
是子进程的ExitStatus
的future,当tokio_process::Child
被丢弃时,子进程将被终止。可以通过Child::forget
方法恢复标准库的行为。
依赖
约3.5MB
约61K SLoC