首页 文章

在Rust中生成进程时重定向stdio的正确方法是什么?

提问于
浏览
3

我看到两种方法(Rust v0.9) . 对于下面的示例,假设我想将STDOUT重定向到某个文件 .

第一种方法是获取文件的文件描述符,然后将其传递给 std::run::ProcessOptions 结构 . 以下是 std::run::process_status 的用法:

let mut opt_prog = Process::new(prog, args, ProcessOptions {
    env: None,
    dir: None,
    in_fd:  Some(unsafe { libc::dup(libc::STDIN_FILENO)  }),
    out_fd: Some(unsafe { libc::dup(libc::STDOUT_FILENO) }),
    err_fd: Some(unsafe { libc::dup(libc::STDERR_FILENO) })
});

它获得了STDIN,STDOUT和STDERR的常用文件描述符并设置它们 . But how do I get the file descriptor for some arbitrary File I've opened in Rust? 我还没有办法做到这一点 .

第二个选项是通过 ProcessOptions::new() 使用默认的ProcessOptions,它打开stdin,stdout和stderr的管道并让你 grab 它们,如下所示:

let pgm = "ls";
let args = ~[~"-lh"];

match Process::new(pgm, args, ProcessOptions::new()) {
    None => println("fubar"),
    Some(mut p) => {
        {
            let process = &mut p;
            let rdr = process.output();  // grab STDOUT output
            let out = rdr.read_to_str();
            // write output to your file of choice here
        }
        p.close_input();
        p.close_outputs();
        p.finish();
    }
}

我更喜欢第一种方式,但我怀疑第二种方式是惯用的方式 .

我不喜欢第二个选项是如果我只想重定向STDOUT而不是其他选项?我现在必须调用 process.error() 并将其写回STDERR,这看起来很愚蠢 . 我还必须为STDIN做类似的事情,因为它也被包裹在管道中 .

关于最佳方式的想法?

1 回答

  • 2

    使用std::os::unix::AsRawFd trait,它使用as_raw_fd方法扩展与平台无关的std::io::fs::File以返回文件描述符 .

    使用此和其他特定于Unix的扩展的一种便捷方法是导入std::os::unix::prelude模块 . 特别是,我写的最初回答问题的例子实际上与文档中的example相同:

    #![feature(globs)]
    
    use std::io::fs::File;
    use std::os::unix::prelude::*;
    
    fn main() {
        let p = Path::new("/etc/passwd");
        let f = File::open(&p).unwrap();
        let fd = f.as_raw_fd();
        println!("{} fd: {}", p.as_str().unwrap(), fd);
    }
    

相关问题