如何从 Rust 进程内部重定向 stderr?

问题描述 投票:0回答:2

我正在尝试从进程内部重定向

Stderr
文件描述符,但似乎没有它的实现,并且我没有看到与 C/C++ 中的
dup2
类似的任何内容的明确路线。

我已经尝试过:

  • 直接实现
    Read
    (
    impl Read for Stderr
    ),但需要整个代码库才能覆盖。
  • 消耗文件描述符中的数据,然后进入

    File
    ,然后进入
    ReadBuf

    trait FDReader {
        fn consume(&mut self);
    }
    
    impl FDReader for Stderr {
        fn consume(&mut self) {
            let f = std::fs::File::from_raw_fd(self.as_raw_fd());
            let mut extract = String::new();
            BufReader::new(f).read_to_string(&mut extract);
        }
    }
    

    我专注于

    consume
    ,因为我在测试代码时不必完全返回任何内容,尽管这不起作用。

  • 由于我在Linux系统上运行,而且我不打算发布代码,所以我还考虑过重定向

    /proc/self/fd/2 -> /dev/null
    ,然后当我想写入那里时返回原始指针引用。对于这个范围来说,这已经超出了极限。

我也想过直接使用

libc::dup2
- 尽管我已经厌倦了。

rust pipe stderr
2个回答
9
投票

标准库中没有办法做到这一点1gag crate 允许将 stderr 或 stdout 重定向到文件或不重定向到任何内容,但它仅适用于 *nix 系统。

从不同的角度来看问题,我鼓励您根本不直接使用 stdout 或 stderr 。相反,使用“依赖注入”来传递可写入的值。不要使用 println,而使用

writeln

另请参阅:

    如何测试标准输入和标准输出?

1

这不是严格正确的。您是否注意到在测试期间stdout 和 stderr 没有输出?这是因为编译器(和测试套件)使用了一对不稳定的隐藏函数,它们允许更改 stdout 和 stderr 的线程本地实例。 另请参阅:

    为什么不打印!从事 Rust 单元测试?

2
投票
libc crate

在较低级别上完成此操作。 即,在程序打开更多文件之前,删除并替换标准文件描述符 0 (stdin)、1 (stdout) 和 2 (stderr)。

它依赖于这样一个事实:

libc

将为新打开的文件分配可用的第一个(最低)描述符。这是由 POSIX

保证的。
在 C 语言中,可以使用

    FILE* stdout
  •  重新分配 
    fdopen(),并且,当
    printf()
    和其他人使用
    FILE* stdout
     时,这就能达到目的。
    但是 Rust 的标准库使用文件描述符,因此我们必须依赖操作系统或 
    libc
  • 实现细节。
  • 我在此示例中替换了 
  • stdout
描述符。它可以在 MacOS 上运行。

use std::ffi::c_char;
use libc;


fn main() {

    unsafe {
        let out_file_path = "console.txt".to_string().as_ptr() as *const c_char;
        // let open_flag = libc::O_WRONLY | libc::O_CREAT | libc::O_APPEND | libc::FD_CLOEXEC;

        libc::close(libc::STDOUT_FILENO);
        let new_fd = libc::creat(out_file_path, libc::S_IRUSR | libc::S_IWUSR);
        if new_fd < 0 {
            libc::perror(std::ptr::null());
        }
        eprintln!("new fd: {}, expected {}", new_fd, libc::STDOUT_FILENO);
    }

    println!("Yohoho!");
}

还必须有一种在 Windows 上执行此操作的方法,就像
这个问题
中那样,但我会将其作为练习留给读者。

© www.soinside.com 2019 - 2024. All rights reserved.