如何重定向stdout& stderr当前进程?

时间:2018-04-13 13:47:44

标签: c++

我的应用程序加载各种使用printf()等的共享库来打印诊断信息。但是,我需要将这些诊断重定向到Android logcats。这里的一般想法是能够向发送到printf()的日志注册某种回调,这样我就可以在任何我想要的地方重定向它们(这使得问题与平台无关,我希望如此)。

我在SO上找到的大部分答案都涉及到进程,但是对我来说情况并非如此。此外,我见过的解决方案涉及fork(),这导致我的进程被多次有效克隆,而我的应用程序不是为此而设计的。

我有什么选择?我只想重定向在我的应用程序自己的运行会话中打印的日志,即在同一地址空间内。我不需要支持子流程等管道。我不确定这是否会简化事情。

请注意,我可以使用此解决方案特定于Linux。

1 个答案:

答案 0 :(得分:1)

使用std::freopen

#include <cstdio>
#include <iostream>

int main() {
  std::printf("This will be printed to console.\n");
  if(std::freopen("log.txt", "w", stdout)) {
      std::printf("This will be redirected to log.txt\n");
      std::cout << "This will also be redirected.\n";
      std::fclose(stdout);
  }
}

See it live!

<小时/> stderr也可以这样做。一个更难的问题实际上是能够使用&#34; old&#34;重新打开之后又重新打开了。 std::freopen关闭旧的文件描述符,因此我们必须复制它并将它与我们的邪恶重定向分开。这是一个POSIX方式(不是标准的C ++):

#include <cstdio>
#include <iostream>

#include <unistd.h>

int main() {
  auto actual_stdout = fdopen(dup(fileno(stdout)), "w");
  std::printf("This will be printed to console.\n");
  if(std::freopen("log.txt", "w", stdout)) {
      std::printf("This will be redirected to log.txt.\n");
      std::cout << "This will also be redirected.\n";
      std::fclose(stdout);
  }

  // Note: using fprintf. C++ streams will still not work.
  std::fprintf(actual_stdout, "This will be printed into the console, too.\n");
}

See it Live!