Van Liedekerke Franky <[EMAIL PROTECTED]> writes:
> Hi,
> 
> I'm using tcpserver and cyclog to log qmail and qmail-smtpd. Now I would
> like to know how to combine these two: in the qmail log I see who mailed to
> whom, but I don't know the IP address, this is in the qmail-smtpd log. So
> how can I combine these two logs?

Sort them...

% sort this-log that-log | tailocal

Here is a perl script that does this in a somewhat more comfortable
fashion.  It extracts a time-slice from the qmail-related logs and
merges them together.

You may need to change the names of the log directories, near the
beginning of the script.  Note: this script is strictly for raw cyclog 
files.  They must be named @<14-digit-timestamp> with each line
beginning with an accustamp time value.  Filenames ending in .gz will
be decompressed automatically.

You also need the Time::ParseDate module, available on CPAN.

================================================================
#!/usr/bin/perl -w

# Display merged pop3d, smtpd and qmail-send logs

# fdc, 1998-07-15

use strict;
use Time::ParseDate;
use Getopt::Std;

use vars qw($opt_g $opt_h $opt_p $opt_q $opt_s $opt_t);

my $pop3log = '/var/log/pop3d';
my $sendlog = '/var/log/qmail-send';
my $smtplog = '/var/log/smtpd';

getopts('g:hpqst') and !$opt_h or die <<EOT;
Usage:
$0 [ flags ] [ <start> ] [ to|bis <end> ]

flags:
 -g re  only show lines matching re (grep)
 -p     show POP3 log         \\
 -q     show qmail-send log   | show all logs if none of pqs are given
 -s     show qmail-smtpd log  /
 -t     test (just show the start and end times)

start and end are date/time specifications (see man Time::ParseDate)
default: <start> = now -1 minute; <end> = <start> +1 minute
EOT

my $now = time;
my($start,$end);
my @extra = (PREFER_PAST=>1, UK=>1, WHOLE=>1);
if (@ARGV) {
    my($from,$x,$till) =
        split / (through|thru|to|until|till|bis) /, "@ARGV";
    $start = parsedate($from, @extra);
    die "$from?\n" unless $start;
    if ($till) {
        push @extra, (NOW=>$start) unless $till =~ /now/;
        $end = parsedate($till, @extra);
        die "$till?\n" unless $end;
    }
    else { $end = $start+60 }
}
else {
    $start = $now-60;
    $end = $now;
}

if ($opt_t) {
    print isodate($start), " -> ", isodate($end), "\n";
    exit 0;
}

my @files = ();
push @files, $pop3log if $opt_p;
push @files, $sendlog if $opt_q;
push @files, $smtplog if $opt_s;
@files = ($pop3log, $sendlog, $smtplog) unless @files;

my $tmp = "/tmp/mail-log.$$";
open(OUT, "|sort|tailocal >$tmp") or
    die "Can't create output pipe: $!\n";

$SIG{PIPE} = 'IGNORE';
$SIG{__DIE__} = sub { close OUT; unlink $tmp; die @_ };

foreach my $file (@files) {
    scan($file, $start, $end);
}

close(OUT) or die "Pipe error: $!\n";

open(IN, $tmp) or die "Can't read results file ($tmp): $!\n";
print while (<IN>);
close(IN);    
unlink $tmp;
exit 0;

sub scan {
    my($d,$s,$e) = @_;
    opendir(D, $d) or die "Can't open $d: $!\n";
    my @logs = sort grep /^@/, readdir(D);
    closedir(D);
    my $limit = sprintf "\@%014d", $s;
    while (@logs > 1) {
        last if $logs[1] gt $limit;
        shift @logs;
    }
    foreach my $f (@logs) {
        $f = "$d/$f";
        $f = "gzip -cdq 2>/dev/null $1|" if $f =~ /(.*\.gz)$/;
        open(F, $f) or die "Can't read $f: $!\n";
        while (<F>) {
            next unless /^(\d+)/;
            next unless $1 >= $s;
            last unless $1 <= $e;
            next if $opt_g and !/$opt_g/o;
            print OUT;
        }
        close(F);
    }
}

sub isodate {
    my(@t) = localtime $_[0];
    sprintf("%04d-%02d-%02d %02d:%02d:%02d",
            $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);
}


-- 
Frank Cringle,      [EMAIL PROTECTED]
voice: (+49 2304) 467101; fax: 943357

Reply via email to