14 个版本

0.3.0-alpha.22019 年 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

Download history 1165/week @ 2024-03-14 1286/week @ 2024-03-21 1503/week @ 2024-03-28 1303/week @ 2024-04-04 1474/week @ 2024-04-11 1377/week @ 2024-04-18 1457/week @ 2024-04-25 1295/week @ 2024-05-02 1523/week @ 2024-05-09 1415/week @ 2024-05-16 1460/week @ 2024-05-23 1392/week @ 2024-05-30 1430/week @ 2024-06-06 1221/week @ 2024-06-13 1240/week @ 2024-06-20 801/week @ 2024-06-27

4,964 每月下载量
少于 17 crates 中使用

MIT 许可证

575KB
10K SLoC

tokio-process

为 Tokio 实现的进程管理

许可证

本项目采用 MIT 许可证

贡献

除非您明确表示,否则您提交给 Tokio 的任何有意包含的贡献都将按 MIT 许可证许可,不附加任何额外条款或条件。


lib.rs:

为 Tokio 实现异步进程管理。

该包提供了一个 Command 结构体,该结构体模仿了标准库中 std::process::Command 类型的接口,但提供了创建进程的函数的异步版本。这些函数(spawnstatusoutput 及其变体)返回与 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