子进程与管道的交互

Beginner

This tutorial is from open-source community. Access the source code

简介

在本实验中,将演示如何使用 std::Child 结构体来表示正在运行的子进程,以及它如何通过管道与 stdinstdoutstderr 句柄进行交互。

注意:如果实验未指定文件名,你可以使用任何你想要的文件名。例如,你可以使用 main.rs,并通过 rustc main.rs &&./main 进行编译和运行。

管道

std::Child 结构体表示一个正在运行的子进程,并通过管道公开 stdinstdoutstderr 句柄,以便与底层进程进行交互。

use std::io::prelude::*;
use std::process::{Command, Stdio};

static PANGRAM: &'static str =
"the quick brown fox jumped over the lazy dog\n";

fn main() {
    // 启动 `wc` 命令
    let process = match Command::new("wc")
                              .stdin(Stdio::piped())
                              .stdout(Stdio::piped())
                              .spawn() {
        Err(why) => panic!("无法启动 wc: {}", why),
        Ok(process) => process,
    };

    // 向 `wc` 的 `stdin` 写入一个字符串。
    //
    // `stdin` 的类型为 `Option<ChildStdin>`,但由于我们知道这个实例一定有一个,所以可以直接 `unwrap` 它。
    match process.stdin.unwrap().write_all(PANGRAM.as_bytes()) {
        Err(why) => panic!("无法写入 wc 的 stdin: {}", why),
        Ok(_) => println!("已将全字母句发送到 wc"),
    }

    // 因为 `stdin` 在上述调用之后不再存在,所以它会被 `drop`,管道也会被关闭。
    //
    // 这非常重要,否则 `wc` 不会开始处理我们刚刚发送的输入。

    // `stdout` 字段的类型也是 `Option<ChildStdout>`,所以也必须解包。
    let mut s = String::new();
    match process.stdout.unwrap().read_to_string(&mut s) {
        Err(why) => panic!("无法读取 wc 的 stdout: {}", why),
        Ok(_) => print!("wc 的响应为:\n{}", s),
    }
}

总结

恭喜你!你已经完成了管道实验。你可以在 LabEx 中练习更多实验来提升你的技能。