Re: Logging (was Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.) - Mailing list pgsql-ports

From Palle Girgensohn
Subject Re: Logging (was Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.)
Date
Msg-id 39294C0D.F53BE202@partitur.se
Whole thread Raw
In response to Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.  (Thomas Good <tomg@admin.nrnet.org>)
Responses Re: Logging (was Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.)
List pgsql-ports
Tom Lane wrote:
>
> Lamar Owen <lamar.owen@wgcr.org> writes:
> > The real problem with redirecting the postmaster output is the issue
> > of log rolling, which is impossible to do in the 'classic'
> > stderr/stdout redirect UNLESS you throw down postmaster when rolling
> > the log (unless you know a trick I don't).

I think I do ;-) read on...

> Yes.  I think ultimately we will have to do some logging support code of
> our own to make this work the way we want.  My thought at the moment is
> there's nothing wrong with logging to stderr, as long as there's some
> code somewhere that periodically closes stderr and reopens it to a new
> log file.  There needn't be a lot of code involved, we just need a
> well-thought-out spec for how it should work.  Comments anyone?
>
>                         regards, tom lane

I really enjoy using apache's rotatelogs program. stderr is
redirected through a pipe to a very small and robust C program,
rotatelogs, that takes as arguments number of seconds between
log rotates and the log filename. Logs are rotated every
argv[2] seconds. The rotatelogs program takes care of closing
and reopening, and nothing has to done from the application,
just start postmaster with '2>&1 | rotatelogs ...' at the end,
and log to stderr.

Also, BSD license! :)

For reference, I enclose the program as an attachment; it's
less than 100 lines. Also, here's the man page:

Name
       rotatelogs - rotate Apache logs without having to kill
the
       server

Synopsis
       rotatelogs logfile rotationtime

Description
       rotatelogs is a simple program for use in conjunction
with
       Apache's  piped  logfile  feature  which  can be used
like
       this:

          TransferLog    "|rotatelogs
/path/to/logs/access_log
       86400"

       This creates the files /path/to/logs/access_log.nnnn
where
       nnnn is the system time at which the log nominally
starts
       (this time will always be a multiple of the rotation
time,
       so you can synchronize cron scripts with it).  At the
end
       of  each  rotation time (here after 24 hours) a new log
is
       started.

Options
       logfile
              The path plus basename of the logfile.  The
suffix
              .nnnn is automatically added.

       rotationtime
              The rotation time in seconds.

See Also
       httpd(8)/*
 * Simple program to rotate Apache logs without having to kill the server.
 *
 * Contributed by Ben Laurie <ben@algroup.co.uk>
 *
 * 12 Mar 1996
 */


#define BUFSIZE        65536
#define MAX_PATH    1024

#include "ap_config.h"
#include <time.h>
#include <errno.h>
#include <fcntl.h>

int main (int argc, char **argv)
{
    char buf[BUFSIZE], buf2[MAX_PATH];
    time_t tLogEnd = 0;
    time_t tRotation;
    int nLogFD = -1;
    int nRead;
    char *szLogRoot;

    if (argc != 3) {
    fprintf(stderr,
        "%s <logfile> <rotation time in seconds>\n\n",
        argv[0]);
#ifdef OS2
    fprintf(stderr,
        "Add this:\n\nTransferLog \"|%s.exe /some/where 86400\"\n\n",
        argv[0]);
#else
    fprintf(stderr,
        "Add this:\n\nTransferLog \"|%s /some/where 86400\"\n\n",
        argv[0]);
#endif
    fprintf(stderr,
        "to httpd.conf. The generated name will be /some/where.nnnn "
        "where nnnn is the\nsystem time at which the log nominally "
        "starts (N.B. this time will always be a\nmultiple of the "
        "rotation time, so you can synchronize cron scripts with it).\n"
        "At the end of each rotation time a new log is started.\n");
    exit(1);
    }

    szLogRoot = argv[1];
    tRotation = atoi(argv[2]);
    if (tRotation <= 0) {
    fprintf(stderr, "Rotation time must be > 0\n");
    exit(6);
    }

    for (;;) {
    nRead = read(0, buf, sizeof buf);
    if (nRead == 0)
        exit(3);
    if (nRead < 0)
        if (errno != EINTR)
        exit(4);
    if (nLogFD >= 0 && (time(NULL) >= tLogEnd || nRead < 0)) {
        close(nLogFD);
        nLogFD = -1;
    }
    if (nLogFD < 0) {
        time_t tLogStart = (time(NULL) / tRotation) * tRotation;
        sprintf(buf2, "%s.%010d", szLogRoot, (int) tLogStart);
        tLogEnd = tLogStart + tRotation;
        nLogFD = open(buf2, O_WRONLY | O_CREAT | O_APPEND, 0666);
        if (nLogFD < 0) {
        perror(buf2);
        exit(2);
        }
    }
    if (write(nLogFD, buf, nRead) != nRead) {
        perror(buf2);
        exit(5);
    }
    }
}

pgsql-ports by date:

Previous
From: Tom Lane
Date:
Subject: Logging (was Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.)
Next
From: Peter Eisentraut
Date:
Subject: Re: Logging (was Re: [GENERAL] PostgreSQL 7.0-2 RPMset released.)