从Rust生成的子进程的重定向输出

时间:2017-05-13 05:36:54

标签: process io rust

我需要重定向生成的子进程的输出。这就是我尝试的但是它不起作用:

Command::new(cmd)
    .args(&["--testnet",
            "--fast",
            format!("&>> {}", log_path).as_str()])
    .stdin(Stdio::piped())
    .stdout(Stdio::inherit())
    .spawn()

2 个答案:

答案 0 :(得分:3)

在启动其他程序时,您无法使用>重定向输出。像>>>|和类似的运算符由shell解释,并不是启动程序的本机功能。由于Command API没有模拟shell,因此无法正常工作。因此,不必在args中传递它,而是必须使用process API的其他方法来实现您想要的效果。

短暂的节目

如果要启动的程序通常立即完成,您可能只想等到它完成并收集其输出。然后,您只需使用Command::output()

即可
use std::process::Command;
use std::fs::File;
use std::io::Write;

let output = Command::new("rustc")
    .args(&["-V", "--verbose"])
    .output()?;

let mut f = File::create("rustc.log")?;
f.write_all(&output.stdout)?;

Playground

注意:上面的代码必须在一个返回Result的函数中,以便?运算符起作用(它只是传递错误)。< / p>

长期计划

但也许你的节目不是短暂的,你不想等到它完成任何输出之后才能完成。在这种情况下,您应该捕获标准输出并调用Command::spawn()。然后,您可以访问实施Read的{​​{3}}:

use std::process::{Command, Stdio};
use std::fs::File;
use std::io;

let child = Command::new("ping")
    .args(&["-n", "10", "google.com"])
    .stdout(Stdio::piped())
    .spawn()?;

let mut f = File::create("ping.log")?;
io::copy(&mut child.stdout.unwrap(), &mut f)?;

ChildStdout

这样,每次命令输出新数据时都会动态写入ping.log

答案 1 :(得分:2)

要直接使用文件作为输出而不从管道进行中间复制,您必须传递文件描述符。代码是特定于平台的,但是通过条件编译,您也可以在Windows上使用它。

let f = File::create("foo.log").unwrap();
let fd = f.as_raw_fd();
// from_raw_fd is only considered unsafe if the file is used for mmap
let out = unsafe {Stdio::from_raw_fd(fd)};
let child = Command::new("foo")
    .stdout(out)
    .spawn().unwrap();