我尝试从进程内部重定向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
--尽管我已经厌倦了。
2条答案
按热度按时间kmbjn2e31#
gag crate允许将stderr或stdout重定向到一个文件或不重定向到任何文件,但它只适用于 *nix系统。
从另一个Angular 来看这个问题,我建议您不要直接使用stdout或stderr,而是使用 * 依赖注入 * 来传递可以写入的值。
另请参阅:
1这并不是 * 严格 * 正确的。你注意到stdout and stderr are not output during tests了吗?这是因为编译器(和测试套件)使用了一对不稳定的隐藏函数,它们允许更改stdout和stderr的线程本地示例。
另请参阅:
q35jwt9p2#
在POSIX系统(Linux/BSD/MacOS)上,有一个不安全的(不止一种方式)黑客,让你在一个较低的级别上,使用libc crate。
也就是说,在程序打开更多的文件之前,拖动并替换标准文件描述符0(stdin)、1(stdout)和2(stderr)。
它依赖于
libc
通常将第一个(最低)可用描述符分配给新打开的文件的事实。遗憾的是,不能保证(我知道)它总是这样工作。FILE* stdout
可以用fdopen()
重新赋值,并且,由于printf()
和其他函数使用FILE* stdout
,这样就可以了。libc
实现细节。在这个例子中我用
stdout
描述符代替,它在MacOS上工作。在Windows上也一定有办法做到这一点,就像在this question中一样,但我将把这作为一个练习留给读者。