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

Con*_*ine 4 io process rust

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

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

Luk*_*odt 6

>启动另一个类似的程序时,您无法重定向输出。运营商如>>>|以及类似的是由你的shell来解释,并且不启动程序的本地功能。由于CommandAPI 不模拟外壳,因此这将不起作用。因此,args您必须使用processAPI 的其他方法来实现您想要的,而不是传递它。

短暂的节目

如果要启动的程序通常立即完成,您可能只想等到它完成并收集其输出。然后你可以简单地使用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)?;
Run Code Online (Sandbox Code Playgroud)

游乐场

注意:上面的代码必须在一个返回 a 的函数中,Result以便?操作符工作(它只是向上传递错误)。

长寿计划

但也许你的程序不是短暂的,你不想等到它完成后再对输出做任何事情。在这种情况下,您应该捕获 stdout 并调用Command::spawn(). 然后你可以访问ChildStdoutwhich 实现Read

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

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

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

游乐场

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

  • @KostyaKrivomaz 你试过 `tail -f` 吗?否则视图不会更新。我刚刚尝试过,它确实对我有用...... (2认同)

the*_*472 6

要直接使用文件作为输出而不需要从管道进行中间复制,您必须传递文件描述符。该代码是特定于平台的,但通过条件编译,您也可以使其在 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();
Run Code Online (Sandbox Code Playgroud)


小智 6

他们添加了一个新的(2017 年 7 月 6 日https://github.com/rust-lang/rust/pull/42133std::process::Stdio::from函数,该函数也接受文件并适用于 Windows 和 Unix 系统。例子:

use std::fs::File;
use std::process::Command;

fn main() {
    let f = File::create("path/to/some/log.log").unwrap();
    let mut cmd = Command::new("some command")
        .stdout(std::process::Stdio::from(f))
        .spawn()
        .unwrap();
    cmd.wait().unwrap();
}
Run Code Online (Sandbox Code Playgroud)