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

时间:2015-08-13 15:14:49

标签: rust

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

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

这听起来不错吗?

我的两个实际问题:

  1. 每个流程是否有更简单的方法不涉及“读取线程”?

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

  3. 请提供具体示例,了解如何实际流式传输输出,而不仅仅是有关如何进行输出的一般性建议......

    更具体地说,这是the default example of using 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());
    

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

1 个答案:

答案 0 :(得分:2)

虽然接受的答案是正确的,但它不包括非平凡的案例。

要流式输出并手动处理,请使用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\\*"));
}

另见Merge child process stdout and stderr关于同时从stderr和stdout捕获输出。