Re: Plan B for log rotation support: borrow Apache code

Поиск
Список
Период
Сортировка
От Bruce Momjian
Тема Re: Plan B for log rotation support: borrow Apache code
Дата
Msg-id 200305240133.h4O1Xq326394@candle.pha.pa.us
обсуждение исходный текст
Ответ на Re: Plan B for log rotation support: borrow Apache code  (Tom Lane <tgl@sss.pgh.pa.us>)
Список pgsql-hackers
Here are the log scripts posted by Andrew Sullivan and Peter E.

---------------------------------------------------------------------------

Tom Lane wrote:
> Peter Eisentraut <peter_e@gmx.net> writes:
> > Or we could take the one I posted, which does exactly the same thing as
> > Apache's (at least about a year ago, not sure where the APR plays in
> > nowadays), thus shortcircuiting that porting effort.
>
> I'd forgotten that one.  Where is it again?
>
>             regards, tom lane
>
> ---------------------------(end of broadcast)---------------------------
> TIP 1: subscribe and unsubscribe commands go to majordomo@postgresql.org
>

--
  Bruce Momjian                        |  http://candle.pha.pa.us
  pgman@candle.pha.pa.us               |  (610) 359-1001
  +  If your life is a hard drive,     |  13 Roberts Road
  +  Christ can be your backup.        |  Newtown Square, Pennsylvania 19073
#!/usr/local/bin/perl
#
#pglog-rotator
#Copyright (c) Liberty RMS 2001-2003
#This file may be distributed under the same terms as PostgreSQL
#This file comes with NO WARRANTY WHATSOEVER
#
#

use IPC::Open3;
use IO::Handle;

$err_log_file='/path/to/logs/stderr_pg.log';
$out_log_file='/path/to/logs/stdout_pg.log';

#### log size in MBytes
$size_limit=1;

#### rotate nn files
$max_logs=7;

#### postgres cmd
# it is best if you set $PGDATA
# and use the $PATH to call just postmaster.
# That makes the output of 'ps -auxww' more valuable
$command = 'postmaster';


#######
sub HUP_SIGNAL {
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
    $gmtime = sprintf ("%.2d/%.2d/%.4d %.2d:%.2d:%.2d: ",  $mon+1, $mday, 1900+$year, $hour, $min, $sec);
        print "$gmtime: SIGHUP received. Ignored.\n";
}
$SIG{HUP} = \&HUP_SIGNAL;


open(LOG, ">>$err_log_file");
autoflush LOG 1;
open(OUT_LOG, ">>$out_log_file");
autoflush OUT_LOG 1;

$cnt = $max_logs;
$size_limit=$size_limit * 1024 * 1024;

### postgres 7.1.3 writes to stderr in any debug_level (0 to 16)
sub read_stderr
{
    while(<ERRFH>)
    {
    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($err_log_file);
    if ( $size > $size_limit ) {
        close LOG;

        while ($cnt > 0) {
            $old_log=sprintf("%s.%s", $err_log_file, $cnt);
            $new_log=sprintf("%s.%s", $err_log_file, $cnt-1);
            rename $new_log, $old_log;
            $cnt--;
        }
        rename $err_log_file, $new_log;
        $cnt = $max_logs;
        open(LOG, ">>$err_log_file");
    }
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
    $gmtime = sprintf ("%.2d/%.2d/%.4d %.2d:%.2d:%.2d: ",  $mon+1, $mday, 1900+$year, $hour, $min, $sec);
    print LOG "$gmtime $_";
    }

}

### postgres 7.1.3 writes to stdout in debug_level 3 to 16
sub read_stdout
{
    while(<RDRFH>)
    {
    ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size, $atime,$mtime,$ctime,$blksize,$blocks) = stat($out_log_file);
    if ( $size > $size_limit ) {
        close OUT_LOG;

        while ($cnt > 0) {
            $old_log=sprintf("%s.%s", $out_log_file, $cnt);
            $new_log=sprintf("%s.%s", $out_log_file, $cnt-1);
            rename $new_log, $old_log;
            $cnt--;
        }
        rename $out_log_file, $new_log;
        $cnt = $max_logs;
        open(OUT_LOG, ">>$out_log_file");
    }
    ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = gmtime(time);
    $gmtime = sprintf ("%.2d/%.2d/%.4d %.2d:%.2d:%.2d: ",  $mon+1, $mday, 1900+$year, $hour, $min, $sec);
    print OUT_LOG "$gmtime $_";
    }

}


$pid = open3(\*WTRFH, \*RDRFH, \*ERRFH, $command);

printf "postmaster [$pid] started: ";

print "$command\n";
print "STDERR log file: $err_log_file\n";
print "STDOUT log file: $out_log_file\n";
printf ("size limit: %.3f MBytes, ", $size_limit / 1024 / 1024);
print "max logs: $max_logs\n";


# read stdout from postmaster
if (fork() == 0) {    ## this is the child
    read_stdout();
    exit(0);
}

read_stderr();

printf "postmaster [$pid] killed.\n\n";

#include "c.h"

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>

#include "pqsignal.h"

volatile static int hangup_flag = 0;


static void
signalhandler(SIGNAL_ARGS)
{
    hangup_flag = 1;
}


#define BUF_SIZE 8192
#define MAX_ERRORS 200

#define MAX_ERRORS_CHECK() do { errcount++; if (max_errors > 0 && errcount >= max_errors) exit(2); } while(0)

int
main(int argc, char *argv[])
{
    const char *filename;
    int fd = -1;
    static char buf[BUF_SIZE];
    unsigned int errcount = 0;
    unsigned int max_errors = MAX_ERRORS;

    if (argc != 2)
    {
        fprintf(stderr, "%s: missing required argument\n", argv[0]);
        fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
        exit(1);
    }

    if (strcmp(argv[1], "--help")==0)
    {
        printf("this should be a help message...\n");
        exit(0);
    }

    filename = argv[1];

    fd = open(filename, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND, 0666);
    if (fd < 0)
    {
        fprintf(stderr, "%s: could not open file %s: %s\n",
                argv[0], filename, strerror(errno));
        exit(1);
    }

    pqsignal(SIGUSR1, signalhandler);

    for (;;)
    {
        int read_bytes;
        int written_bytes;
        char * buf_ptr;

        read_bytes = read(0, buf, sizeof(buf));
        if (read_bytes < 0)
        {
            if (errno == EINTR)
                continue;
            else
            {
                fprintf(stderr, "*** %s: read error from %s: %s\n",
                        argv[0], filename, strerror(errno));
                MAX_ERRORS_CHECK();
            }
        }
        if (read_bytes == 0)
        {
            /* end of file, postmaster exited? */
            close(fd);
            exit(0);
        }

        if (hangup_flag)
        {
            int fdnew;

            fdnew = open(filename, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND, 0666);
            if (fdnew < 0)
            {
                fprintf(stderr, "*** %s: could not open new output file %s: %s\n",
                       argv[0], filename, strerror(errno));
                MAX_ERRORS_CHECK();
            }
            else
            {
                close(fd);
                fd = fdnew;
            }
            hangup_flag = 0;
        }

        buf_ptr = buf;
        do
        {
            written_bytes = write(fd, buf_ptr, read_bytes);
            if (written_bytes < 0)
            {
                if (errno == EINTR)
                    continue;
                fprintf(stderr, "*** %s: could not write to file %s: %s\n",
                        argv[0], filename, strerror(errno));
                MAX_ERRORS_CHECK();

                break;
            }
            if (written_bytes < read_bytes)
            {
                buf_ptr += written_bytes;
                read_bytes -= written_bytes;
                continue;
            }
            break;
        } while(1);
    }

    return 127;
}

В списке pgsql-hackers по дате отправления:

Предыдущее
От: Michael Brusser
Дата:
Сообщение: Re: vacuum analyze corrupts database
Следующее
От: Christopher Browne
Дата:
Сообщение: Re: more contrib: log rotator