Как я могу перенаправить вывод в журнал наддува?

У меня есть программа на C ++, использующая журнал форсирования, и я загружаю предоставленную пользователем библиотеку динамических ссылок. Я бы хотел перенаправить stderr в журнал наддува, чтобы в любое время пользовательская библиотека сделала:

std::cerr << "Some stuff";

Это дает тот же результат **, что и:

BOOST_LOG_SEV(log,info) << "Some stuff";

Возможно ли это, и если да, то как мне это сделать?

(Кроме того, я не уверен, что делать с серьезностью … так как cerr << не конфиденциальность информации. Я открыт для предложений по этому вопросу …)

** Под «тем же результатом» я имею в виду, что он регистрируется в том же файле журнала, что и остальные сообщения журнала, и к этим строкам применяется тот же форматер журнала.

2

Решение

Вот моя реализация на C ++ 11. Этот класс может использоваться для чего угодно (не только для повышения) для захвата stdout / stderr построчно и вызова пользовательской функции (может быть лямбда-выражением) для ее обработки.

Предупреждение: если вы перенаправляете stderr а также stdout и использовать Boost, а затем перенаправить stderr будет первый stdout, В противном случае Boost запишет цикл обратной передачи сообщения stderr обратно в stdout, и вы получите запись журнала форсирования в другой записи журнала форсирования.

Пример использования

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)
{
}
};
2

Другие решения

Я думаю, вы можете перенаправить File descriptor STDERR в дескриптор файла вашего потока [вы должны получить описание файла вашего потока], используя dup/dup2 api [это posix api]

-2

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector