您如何从流程中输出流量?

Dou*_*oug 11 rust

一般来说,我相信我理解这样做的一种方式:

  • 创建一个 Command
  • 使用Stdio::piped()创建一个新的对输出流
  • 配置command.stdout(),和command.stderr()
  • 产生这个过程
  • 创建一个新线程并将stderr和stdout传递给它< - ???
  • 在远程线程中,不断轮询输入并将其写入输出流.
  • 在主线程中,等待进程完成.

听起来不错吗?

我的两个实际问题:

  1. 是否有一种更简单的方法,不涉及每个进程的"读取线程"?

  2. 如果没有更简单的方法,Read::read()需要&mut self; 你如何将它传递到远程线程?

请提供有关如何实际流式传输输出的具体示例,而不仅仅是有关如何执行此操作的通用建议...

更具体地说,这是使用的默认示例spawn:

use std::process::Command;

let mut child = Command::new("/bin/cat")
                        .arg("file.txt")
                        .spawn()
                        .expect("failed to execute child");

let ecode = child.wait()
                 .expect("failed to wait on child");

assert!(ecode.success());
Run Code Online (Sandbox Code Playgroud)

如何更改上面的示例以将child的输出流式传输到控制台,而不是仅仅等待退出代码?

She*_*ter 10

我很乐意接受任何产生长时间运行过程并通过任何方式将输出流输出到控制台的示例.

这听起来像你想要的Stdio::inherit:

use std::process::{Command, Stdio};

fn main() {
    let mut cmd =
        Command::new("cat")
        .args(&["/usr/share/dict/web2"])
        .stdout(Stdio::inherit())
        .stderr(Stdio::inherit())
        .spawn()
        .unwrap();

    // It's streaming here

    let status = cmd.wait();
    println!("Exited with status {:?}", status);
}
Run Code Online (Sandbox Code Playgroud)


Dou*_*oug 6

尽管公认的答案是正确的,但它并不涵盖非平凡的情况。

要流输出并Stdio::piped()手动处理输出,请使用和手动处理.stdout从调用返回的子项上的属性spawn,如下所示:

use std::process::{Command, Stdio};
use std::path::Path;
use std::io::{BufReader, BufRead};

pub fn exec_stream<P: AsRef<Path>>(binary: P, args: Vec<&'static str>) {
    let mut cmd = Command::new(binary.as_ref())
        .args(&args)
        .stdout(Stdio::piped())
        .spawn()
        .unwrap();

    {
        let stdout = cmd.stdout.as_mut().unwrap();
        let stdout_reader = BufReader::new(stdout);
        let stdout_lines = stdout_reader.lines();

        for line in stdout_lines {
            println!("Read: {:?}", line);
        }
    }

    cmd.wait().unwrap();
}

#[test]
fn test_long_running_process() {
    exec_stream("findstr", vec!("/s", "sql", "C:\\tmp\\*"));
}
Run Code Online (Sandbox Code Playgroud)

另请参阅合并子进程stdout和stderr,以了解如何同时捕获stderr和stdout的输出。

  • 这个答案非常有用!快速提问:流读取部分被放在一个单独的范围内的任何特殊原因? (2认同)
  • @PascalPrecht 分隔“cmd”的可变借用,第一个在“stdout”中,第二个在“cmd.wait()”中。今天,编译器会在“cmd.wait()”语句之前自动删除“stdout”,但我认为过去情况并非如此。因此,这里的范围需要限制“stdout”的生命周期。 (2认同)