我有一个使用boost log的C++程序,我加载了一个用户提供的动态链接库。我想将 stderr 重定向到 boost 日志,以便用户的库随时执行:
std::cerr << "Some stuff";
它产生与以下相同的结果**:
BOOST_LOG_SEV(log,info) << "Some stuff";
这可能吗?如果可以,我该怎么做?
(此外,我不确定如何处理严重性...因为 cerr <<
不提供严重性信息。我也愿意接受有关建议...)
** “相同结果”是指它与其余日志消息记录到相同的日志文件中,并且对这些行应用相同的日志格式化程序。
最佳答案
这是我的 C++11 实现。此类可用于任何事情(不仅仅是 boost )以逐行捕获 stdout/stderr 并调用用户函数(可以是 lambda)来处理它。
警告:如果您重定向 stderr
和 stdout
并且正在使用 Boost,那么首先重定向 stderr
,然后是 stdout
。否则,Boost 会将 stderr 消息环回写回 stdout,您将在另一个 boost 日志条目中获得一个 boost 日志条目。
使用示例
cout << "testing out before 1 2 3 " << endl;
cerr << "testing err before 1 2 3 " << endl;
{
StdErrHandler err([](const char* line){
BOOST_LOG_TRIVIAL(error) << "ERROR:" << strlen(line) << " " << line;
});
StdOutHandler out([](const char* line){
BOOST_LOG_TRIVIAL(info) << "OUT:" << strlen(line) << " " << line;
});
cout << "cout testing 1 2 3 " << endl;
cerr << "cerr testing 1 2 3 " << endl;
}
cout << "testing out after 1 2 3 " << endl;
cerr << "testing err after 1 2 3 " << endl;
示例输出
pa-poca$ ./test
testing out before 1 2 3
testing err before 1 2 3
[2014-08-01 12:24:56.468335] [0x000007f89d8990d4] [error] ERROR:19 cerr testing 1 2 3
[2014-08-01 12:24:56.468360] [0x000007f89d8990d4] [info] OUT:19 cout testing 1 2 3
testing out after 1 2 3
testing err after 1 2 3
代码
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <signal.h>
#include <sys/wait.h>
class StdioHandler
{
private:
pid_t pid = 0;
int origfd;
int streamid;
int pipefd[2];
public:
enum class Stream
{
stdout = STDOUT_FILENO,
stderr = STDERR_FILENO
};
StdioHandler(Stream stream, std::function<void(const char*)> callback)
:streamid(static_cast<int>(stream))
{
origfd = dup(streamid);
pipe(pipefd); // create pipe
pid = fork(); //spawn a child process to handle output of pipe
if (pid == 0)
{
char line[256];
FILE* output;
close(pipefd[1]);
output = fdopen(pipefd[0], "r");
if (output)
{
while(fgets(line, sizeof(line), output))
{
int n = strlen(line);
if (n > 0)
if (line[n-1] == '\n') line[n-1] = 0;
callback(line);
}
fclose(output);
}
abort();
} else {
// connect input of pipe to
close(pipefd[0]);
dup2(pipefd[1], streamid);
}
}
~StdioHandler()
{
int status;
usleep(10000);
close(pipefd[1]);
kill(pid,SIGINT);
waitpid(pid, &status, 0);
dup2(origfd, streamid);
}
};
class StdOutHandler : public StdioHandler
{
public:
StdOutHandler(std::function<void(const char*)> callback) :
StdioHandler(Stream::stdout, callback)
{
}
};
class StdErrHandler : public StdioHandler
{
public:
StdErrHandler(std::function<void(const char*)> callback) :
StdioHandler(Stream::stderr, callback)
{
}
};
关于c++ - 如何将输出重定向到 boost 日志?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17915478/