将标准输出重定向到syslog

15

我计划将OpenTibia Server打包为Debian。我想做的其中一件事是通过/etc/init.d启动并将otserv进程作为守护进程。

问题是,我们应该将输出重定向到syslog。这通常是通过syslog()函数完成的。目前,代码中充斥着:

std::cout << "Stuff to printout" << std::endl;

有没有一种适当且易于使用的方法,可以将标准输出和标准错误输出重定向到syslog,而不必替换每个对std::cout等的调用?

5个回答

22
您可以使用logger命令将stdout导入syslog

NAME

 logger - a shell command interface to the syslog(3) system log module

SYNOPSIS

 logger [-isd] [-f file] [-p pri] [-t tag] [-u socket] [message ...]

DESCRIPTION

 Logger makes entries in the system log.  It provides a shell command
 interface to the syslog(3) system log module.

如果你在命令行中没有提供消息,它会读取stdin(标准输入)


5
您可以通过使用rdbuf()命令来重定向C++中的任何流。这个实现有点复杂,但并不是很难。
您需要编写一个streambuf,在overflow()时输出到syslog,并用您的streambuf替换std::cout rdbuf。
以下是一个示例,它将输出到文件(没有错误处理,代码未经测试)。
#include <iostream>
#include <fstream>
using namespace std;

int main (int argc, char** argv) {
   streambuf * yourStreamBuffer = NULL;
   ofstream outputFileStream;
   outputFileStream.open ("theOutputFile.txt");

   yourStreamBuffer = outputFileStream.rdbuf();
   cout.rdbuf(yourStreamBuffer);

   cout << "Ends up in the file, not std::cout!";

   outputFileStream.close();

   return 0;
 }

几乎是我要找的,但“logger”为我提供了额外的信息,特别是如果我只是制作一个包装bash脚本。不过,感谢您提供的信息,很抱歉我不能将两个答案都标记为“答案”。 - Ivan Vučica

4

1
这就是它。如果您也能在此处粘贴您帖子的部分,那将非常好 ;) - Ivan Vučica
1
它几乎不可移植,也不符合标准的POSIX。 - Alnitak
@Mischa 我的意思是,其中推荐的 fopencookie 函数只存在于 glibc(即 Linux 系统)中。 - Alnitak
1
@Mischa: 我其实很希望你可以通过我的链接点击或广告点击获得一些收益,但如果将文本粘贴在答案内部,人们可以更快地看到它。此外,如果你的博客出现了任何问题,答案也会在这里被镜像。 ;) - Ivan Vučica
@Alnitak:Mischa还写了关于fwopen()的文章,该函数存在于包括OS X在内的BSD系统中。这几乎涵盖了所有值得讨论的具有syslog实现的主要平台。对于大多数开发者的需求来说,这已经足够了。当存在这种优雅的解决方案时,我不会疯狂地使用套接字和第二个线程来调用syslog()以符合POSIX标准。 - Ivan Vučica
显示剩余4条评论

2
尝试使用适当的脚本来包装二进制文件的执行,该脚本只需读取标准输出和标准错误,并通过syslog()发送从它们读取的任何数据。这样做不需要对被包装应用程序进行任何代码更改,而且相当容易实现。
如果没有现成的脚本可供使用,写一个也不难。

这似乎是一个非常便携的解决方案,因此这只能让我们拥有两个日志级别:错误和信息。Linux syslog 提供了更多的日志级别。但是,如果我们可以忍受这个小缺点,这里有一篇文章展示了如何实现:http://unix.stackexchange.com/questions/124455/linux-how-to-redirect-stdout-stderr-to-logger - Johan Engblom

1

我刚刚写了一些代码来实现这个功能。它使用的是 ASL 而不是 syslog,并且使用 kevents,因此您可能需要将其移植到不同的系统 API 上(例如使用 syslog 替代 ASL,使用 poll/select 替代 kevent)。

http://cgit.freedesktop.org/xorg/app/xinit/tree/launchd/console_redirect.c

此外,我基本上是在Mountain Lion的libsystem_asl中添加了这个功能。请查看asl_log_descriptor的手册。
例如:
#include <asl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    asl_log_descriptor(NULL, NULL, ASL_LEVEL_INFO, STDOUT_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
    asl_log_descriptor(NULL, NULL, ASL_LEVEL_NOTICE, STDERR_FILENO, ASL_LOG_DESCRIPTOR_WRITE);
    fprintf(stdout, "This is written to stdout which will be at log level info.");
    fprintf(stderr, "This is written to stderr which will be at log level notice.");
    return 0;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接