记录标准输入和标准输出

Logging stdin and stdout

本文关键字:标准输出 标准输入 记录      更新时间:2023-10-16

有没有一种(理想情况下简单而优雅)的方式来记录stdinstdout

请注意,我不打算重定向流。我希望标准流保持功能以与其他软件通信,同时将所有进程间通信写入某个文件。

选项 1:

正如@PaulR建议的那样,您可以使用外部进程,例如tee(在Linux/Mac/Unix上),或者编写自己的进程以循环从stdin读取并写入stdout和另一个文件。

选项 2:

我多年前就用 std::basic_ios::rdbuf 做了这件事std::cout.所要做的就是定义一个类(参见std::filebufstd::streambuf):

class tee_buf : public std::filebuf {
public:
// Not an owing pointer
tee_buf(std::streambuf * other_stream) 
: m_other_stream(other_stream) {}
void swap( tee_buf& rhs );
// No need to override open/close since we need to manage only the file.
// The open/close calls don't touch the other_stream.
protected:
int_type overflow(int_type c = traits_type::eof()) override;
// The parent calls this->overflow(), but then still need to call
// m_other_stream->sync(). This is problematic since m_other_stream
// gets flushed twice.
int sync() override;
pos_type seekoff( off_type off,
std::ios_base::seekdir dir,
std::ios_base::openmode which) override {
return pos_type(off_type(-1)); // ???
}
pos_type seekpos( pos_type sp,
std::ios_base::openmode which) override {
return pos_type(off_type(-1)); // ???
}
....

这对于密集的 IO 更有效,因为它避免了中间人。但在大多数情况下,三通解决方案更简单、更可取。如果性能是一个问题(在大多数情况下不是),则可以使两个流缓冲区共享一个内存缓冲区。也可以使用异步 IO 并行写入两个流。

内存泄漏的用法:

std::cout.rdbuf(new tee_buf(std::cout.rdbuf());

无内存泄漏的使用:

编写一个RAII类来包含tee_buf,以保存原始内容并设置新std::cout.rdbuf()。销毁后恢复std::cout.rdbuf()状态。创建此类的单个实例,它将在构造和销毁时完成肮脏的工作。

至于C风格的stdout:我不相信有办法覆盖它的行为。最多可以使用缓冲内存,但这还不足以获得所需的功能。有了stdout,唯一能做的就是使用类似tee的解决方案。

这应该相当简单 用tee.这将允许您维护任何现有的重定向,同时还将标准/标准输出发送到其他地方(在您的情况下是文件)。这也避免了对现有代码进行任何修改。