248 lines
5.9 KiB
Perl
Executable file
248 lines
5.9 KiB
Perl
Executable file
#!/usr/bin/perl -w
|
|
#
|
|
# $Id: replay-log,v 1.9 2005/08/06 21:00:00 jmates Exp $
|
|
#
|
|
# The author disclaims all copyrights and releases this script into the
|
|
# public domain.
|
|
#
|
|
# Replays logs, simulating the time delays present in the source
|
|
# data. Only supports the standard Unix syslogd(8) format at present.
|
|
#
|
|
# Run perldoc(1) on this script for additional documentation.
|
|
|
|
use POSIX qw(strftime);
|
|
use Time::Local qw(timelocal);
|
|
use Time::HiRes qw(sleep);
|
|
|
|
use Getopt::Std;
|
|
my %opts;
|
|
getopts 'h?r:f:o:s:', \%opts;
|
|
|
|
print_help() if exists $opts{h} or exists $opts{'?'};
|
|
|
|
my ( $previous_epoch, $random_seed, $speed_factor );
|
|
|
|
# increase playback speed
|
|
if ( exists $opts{f} and defined $opts{f} and $opts{f} > 1 ) {
|
|
$speed_factor = $opts{f};
|
|
} else {
|
|
$speed_factor = 1;
|
|
}
|
|
|
|
# use random seed to determine delay for next log entry
|
|
if ( exists $opts{r}
|
|
and defined $opts{r}
|
|
and $opts{r} > 0 ) {
|
|
|
|
$random_seed = $opts{r};
|
|
$previous_epoch = time;
|
|
}
|
|
|
|
# use custom output file
|
|
if ( exists $opts{o} ) {
|
|
open STDOUT, '>', $opts{o}
|
|
or die "error: could not open: errno=$!, file=$opts{o}\n";
|
|
}
|
|
|
|
# leading delay (good if need time to get something else running)
|
|
if ( exists $opts{s} and defined $opts{s} and $opts{s} > 0 ) {
|
|
sleep $opts{s};
|
|
}
|
|
|
|
# force flush on output for better replay of logs
|
|
$| = 1;
|
|
|
|
while (<>) {
|
|
chomp;
|
|
|
|
# TODO will need to read different log formats (standard syslog, squid,
|
|
# apache, custom...): split into "time, rest of data" and have means to
|
|
# output "time with format, rest of data"
|
|
my %data;
|
|
|
|
( $data{rawtime}, $data{suffix} ) =
|
|
$_ =~ m/^ (\w{3} \s\s? \d\d? \s [\d:]{8}) (.*) $/x;
|
|
|
|
$data{epoch} =
|
|
$random_seed
|
|
? $previous_epoch + rand $random_seed
|
|
: syslog_to_epoch( $data{rawtime} );
|
|
|
|
if ( defined $previous_epoch ) {
|
|
my $delay = ( $data{epoch} - $previous_epoch ) / $speed_factor;
|
|
|
|
# KLUGE syslog messages may have different timezones, which results
|
|
# in negative time differences. Workaround: detect and sleep random
|
|
# time value. (TODO use moving average instead?)
|
|
if ( $delay < 0 ) {
|
|
$delay = rand ($random_seed || 3);
|
|
}
|
|
|
|
sleep $delay;
|
|
}
|
|
|
|
# TODO for output, either want original string, or rework with new
|
|
# timestamp based on the current time. Allow templating off %data,
|
|
# different time formatting via strftime.
|
|
if ($random_seed) {
|
|
print epoch_to_str( $data{epoch} ), $data{suffix}, $/;
|
|
} else {
|
|
print $_, $/;
|
|
}
|
|
|
|
$previous_epoch = $data{epoch};
|
|
}
|
|
|
|
sub epoch_to_str {
|
|
# epoch may have .123 microseconds (squid logs), so whack that off
|
|
strftime "%b %d %H:%M:%S", localtime( int $_[0] || 0 );
|
|
}
|
|
|
|
# convert default syslog timestamp into epoch seconds. Uses current
|
|
# year, as syslog does not record the year (nor the timezone, but that's
|
|
# another rant).
|
|
sub syslog_to_epoch {
|
|
my $date = shift;
|
|
my $epoch;
|
|
|
|
my %month_map;
|
|
@month_map{qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)} = 0 .. 11;
|
|
|
|
my ( $month, $day, $hour, $min, $sec ) =
|
|
$date =~ m/^(\w{3}) \s\s? (\d\d?) \s (\d\d):(\d\d):(\d\d)/x;
|
|
$epoch = timelocal $sec, $min, $hour, $day, $month_map{$month},
|
|
1900 + (localtime)[5];
|
|
|
|
return $epoch;
|
|
}
|
|
|
|
sub print_help {
|
|
print <<"HELP";
|
|
Usage: $0 [-o output-file] [-f factor] [-r random-seed] < input-file
|
|
|
|
Replays logs, simulating the time delays present in the source data.
|
|
|
|
Options:
|
|
-h/-? Display this message.
|
|
|
|
-o ff Write output to this file instead of standard out.
|
|
|
|
-f nn Numeric factor to speed replay up by, such as 3600.
|
|
-r nn Specify random seed to rand() for random replay speed.
|
|
-s nn Sleep this long before starting.
|
|
|
|
Run perldoc(1) on this script for additional documentation.
|
|
|
|
HELP
|
|
exit 100;
|
|
}
|
|
|
|
__DATA__
|
|
|
|
=head1 NAME
|
|
|
|
replay-log - replays logs with simulated time delays
|
|
|
|
=head1 SYNOPSIS
|
|
|
|
Replay logs from C</var/log/messages> (may take some time!):
|
|
|
|
$ replay-log </var/log/messages
|
|
|
|
A three second random seed causes faster playback:
|
|
|
|
$ </var/log/messages replay-log -r 3
|
|
|
|
As does using a higher replay factor:
|
|
|
|
$ replay-log -f 3600 </var/log/messages
|
|
|
|
Send C<sshd> logs to a named pipe, read them with C<sec.pl>:
|
|
|
|
$ mkfifo logfile
|
|
$ grep sshd </var/log/messages | replay-log -f 1000 -o logfile &
|
|
$ sec.pl --conf=sshd.conf --input=logfile
|
|
|
|
=head1 DESCRIPTION
|
|
|
|
=head2 Overview
|
|
|
|
Replays log data, simulating the time delays of the log data. Faster
|
|
playback possible via the random seed and factor options. Good for
|
|
replaying logs to tools such as C<swatch> or SEC:
|
|
|
|
http://swatch.sourceforge.net/
|
|
|
|
http://kodu.neti.ee/~risto/sec/
|
|
|
|
Only supports Unix syslogd(8) data at present.
|
|
|
|
=head2 Normal Usage
|
|
|
|
$ replay-log [-o output-file] [-f factor] [-r random-seed] < input-file
|
|
|
|
See L<"OPTIONS"> for details on the command line switches supported.
|
|
|
|
Log data is read from standard input, and sent to standard output,
|
|
unless a custom output file is specified.
|
|
|
|
=head1 OPTIONS
|
|
|
|
This script currently supports the following command line switches:
|
|
|
|
=over 4
|
|
|
|
=item B<-h>, B<-?>
|
|
|
|
Prints a brief usage note about the script.
|
|
|
|
=item B<-o> I<filename>
|
|
|
|
Send output to I<filename> instead of standard out.
|
|
|
|
=item B<-r> I<random-seed>
|
|
|
|
Use I<random-seed> as the random seed to C<rand()>; logs will playback
|
|
using a random delay based on the seed.
|
|
|
|
=item B<-f> I<factor>
|
|
|
|
Speed playback of logs. I<factor> must be a number greater than one;
|
|
higher values lead to faster replays.
|
|
|
|
=item B<-s> I<leading-sleep>
|
|
|
|
Sleep I<leading-sleep> seconds before replaying any logs.
|
|
|
|
=back
|
|
|
|
=head1 BUGS
|
|
|
|
=head2 Reporting Bugs
|
|
|
|
If the bug is in the latest version, send a report to the author.
|
|
Patches that fix problems or add new features are welcome.
|
|
|
|
=head2 Known Issues
|
|
|
|
Only supports Unix syslogd(8) data at present. Output could be formatted
|
|
in different ways and offer better control of timestamp display.
|
|
|
|
=head1 SEE ALSO
|
|
|
|
perl(1)
|
|
|
|
=head1 AUTHOR
|
|
|
|
Jeremy Mates, http://sial.org/contact/
|
|
|
|
=head1 COPYRIGHT
|
|
|
|
The author disclaims all copyrights and releases this script into the
|
|
public domain.
|
|
|
|
=head1 VERSION
|
|
|
|
$Id: replay-log,v 1.9 2005/08/06 21:00:00 jmates Exp $
|
|
|
|
=cut
|