子进程与管道的交互

RustRustBeginner
立即练习

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

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

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

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


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL rust(("Rust")) -.-> rust/BasicConceptsGroup(["Basic Concepts"]) rust(("Rust")) -.-> rust/FunctionsandClosuresGroup(["Functions and Closures"]) rust(("Rust")) -.-> rust/AdvancedTopicsGroup(["Advanced Topics"]) rust(("Rust")) -.-> rust/DataTypesGroup(["Data Types"]) rust(("Rust")) -.-> rust/MemorySafetyandManagementGroup(["Memory Safety and Management"]) rust(("Rust")) -.-> rust/DataStructuresandEnumsGroup(["Data Structures and Enums"]) rust(("Rust")) -.-> rust/ErrorHandlingandDebuggingGroup(["Error Handling and Debugging"]) rust/BasicConceptsGroup -.-> rust/variable_declarations("Variable Declarations") rust/BasicConceptsGroup -.-> rust/mutable_variables("Mutable Variables") rust/DataTypesGroup -.-> rust/string_type("String Type") rust/FunctionsandClosuresGroup -.-> rust/function_syntax("Function Syntax") rust/FunctionsandClosuresGroup -.-> rust/expressions_statements("Expressions and Statements") rust/MemorySafetyandManagementGroup -.-> rust/lifetime_specifiers("Lifetime Specifiers") rust/DataStructuresandEnumsGroup -.-> rust/method_syntax("Method Syntax") rust/ErrorHandlingandDebuggingGroup -.-> rust/panic_usage("panic! Usage") rust/AdvancedTopicsGroup -.-> rust/operator_overloading("Traits for Operator Overloading") subgraph Lab Skills rust/variable_declarations -.-> lab-99274{{"子进程与管道的交互"}} rust/mutable_variables -.-> lab-99274{{"子进程与管道的交互"}} rust/string_type -.-> lab-99274{{"子进程与管道的交互"}} rust/function_syntax -.-> lab-99274{{"子进程与管道的交互"}} rust/expressions_statements -.-> lab-99274{{"子进程与管道的交互"}} rust/lifetime_specifiers -.-> lab-99274{{"子进程与管道的交互"}} rust/method_syntax -.-> lab-99274{{"子进程与管道的交互"}} rust/panic_usage -.-> lab-99274{{"子进程与管道的交互"}} rust/operator_overloading -.-> lab-99274{{"子进程与管道的交互"}} end

管道

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 中练习更多实验来提升你的技能。