15

I'm planning to package OpenTibia Server for Debian. One of the things I want to do is add startup via /etc/init.d and daemonization of the otserv process.

Thing is, we should probably redirect output to syslog. This is usually done via the syslog() function. Currently, the code is swarmed with:

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

Is there a proper, easy to add, way to redirect standard output and standard error output into syslog without replacing every single "call" to std::cout and friends?

Ivan Vučica
  • 9,529
  • 9
  • 60
  • 111

5 Answers5

22

You can pipe your stdout to syslog with the logger command:

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.

If you don't supply a message on the command line it reads stdin

Alnitak
  • 334,560
  • 70
  • 407
  • 495
5

You can redirect any stream in C++ via the rdbuf() command. This is a bit convoluted to implement but not that hard.

You need to write a streambuf that would output to syslog on overflow(), and replace the std::cout rdbuf with your streambuf.

An example, that would output to a file (no error handling, untested code)

#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;
 }
Pieter
  • 17,435
  • 8
  • 50
  • 89
  • Almost what I was looking for, however, "logger" supplies me extra information, especially if I simply produce a wrapper bash script. However, thanks for the information, and I'm so sorry I cannot mark both answers as The Answers(tm). – Ivan Vučica Mar 26 '09 at 10:28
4

Not sure whether a straight "C" answer suffices; but in "C" you can use underlying stdio features to plug the (FILE*) directly into syslog calls, without an intervening "logger" process. Check out http://mischasan.wordpress.com/2011/05/25/redirecting-stderr-to-syslog/

Mischa
  • 2,240
  • 20
  • 18
  • 1
    This is it. It would be great if you would paste portions of your post here, too ;) – Ivan Vučica Oct 23 '11 at 15:28
  • 1
    it's hardly portable, and it's not standard POSIX – Alnitak Oct 23 '11 at 16:57
  • @Ivan: pasting a link is faster than pasting an article. I don't earn revenue from you clicking on my blog link :-) – Mischa Oct 28 '11 at 06:31
  • @Alnitak: what does 'portable' mean here? Portable to Linux distros? Portable to Linux/FreeBSD/OpenBSD? Portable to anything in the Unix family? – Mischa Oct 28 '11 at 06:32
  • @Mischa what I mean is that the `fopencookie` function recommended therein is only present in `glibc` (i.e. Linux systems). – Alnitak Oct 28 '11 at 07:57
  • 1
    @Mischa: I would actually love if you'd earn some revenue from my link-clicking or ad-clicking, but people can more quickly see the text if it's pasted inside the answer. Plus, if anything happens to your blog, the answer will be mirrored here. ;) – Ivan Vučica Oct 28 '11 at 08:42
  • @Alnitak: Mischa also wrote about `fwopen()` that exists on BSD systems, including OS X. This covers pretty much all major platforms that have a syslog implementation worth talking about. For most developers' needs this would be enough. I'm not mad enough to play with sockets and a second thread that would call `syslog()` just to be POSIX compliant when this elegant solution exists. – Ivan Vučica Oct 28 '11 at 08:53
  • If you're prepared to actually change the code at all then you're better off with this C++ specific solution: http://stackoverflow.com/questions/2638654/redirect-c-stdclog-to-syslog-on-unix – Alnitak Oct 28 '11 at 09:30
  • @Mischa I know this is quite old, but SO specifically encourages answers with links elsewhere to ["always quote the most relevant part of an important link, in case the target site is unreachable or goes permanently offline."](http://stackoverflow.com/help/how-to-answer) – daiscog Dec 18 '16 at 20:50
2

Try wrapping the execution of the binary with a suitable script, that just reads stdout and stderr, and send any data read from them on using syslog(). That should work without any code changes in the wrapped application, and be pretty easy.

Not sure if there are existing scripts to pipe into, but writing one shouldn't be hard if not.

unwind
  • 391,730
  • 64
  • 469
  • 606
  • that seems as a very portable solution, thus this will only enable us to have two log levels error and info, the linux syslog has more loglevels at hand. But if we can stand this small drawback, here is a post showing how to accomplish that: http://unix.stackexchange.com/questions/124455/linux-how-to-redirect-stdout-stderr-to-logger – Johan Engblom Oct 09 '15 at 11:07
1

I just wrote some code that will do this. It's using ASL instead of syslog, and it's using kevents, so you may need to port it to different APIs for your system (syslog instead of ASL and poll/select instead of kevent)

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

Furthermore, I basically added this to libsystem_asl on Mountain Lion. Check out the man page for asl_log_descriptor.

Example:

#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;
}
Jeremy Huddleston Sequoia
  • 22,938
  • 5
  • 78
  • 86