251 lines
6.2 KiB
Plaintext
251 lines
6.2 KiB
Plaintext
|
#!/usr/bin/perl
|
||
|
###############################################################################
|
||
|
#
|
||
|
# Copyright (c) 2018 Artica Soluciones Tecnologicas S.L.
|
||
|
#
|
||
|
# grep_log Perl script to search log files for a matching pattern. The last
|
||
|
# searched position is saved in an index file so that consecutive
|
||
|
# runs do not return the same results. The log file inode number is
|
||
|
# also saved to detect log rotation.
|
||
|
#
|
||
|
# This program is free software; you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU General Public License as published by
|
||
|
# the Free Software Foundation; version 2 of the License.
|
||
|
#
|
||
|
# This program is distributed in the hope that it will be useful,
|
||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
|
# GNU General Public License for more details.
|
||
|
#
|
||
|
###############################################################################
|
||
|
use strict;
|
||
|
use File::Basename;
|
||
|
use IO::Compress::Zip qw(zip $ZipError);
|
||
|
use MIME::Base64;
|
||
|
|
||
|
# Be verbose
|
||
|
my $Verbose = 0;
|
||
|
|
||
|
# Index file storage directory, with a trailing '/'
|
||
|
my $Idx_dir=($^O =~ /win/i)?'.\\':'/tmp/';
|
||
|
|
||
|
# Log file
|
||
|
my $Log_file = '';
|
||
|
|
||
|
# Index file
|
||
|
my $Idx_file = '';
|
||
|
|
||
|
# Log file position index
|
||
|
my $Idx_pos = 0;
|
||
|
|
||
|
# Log file inode number
|
||
|
my $Idx_ino = '';
|
||
|
|
||
|
# Log file size
|
||
|
my $Idx_size = 0;
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB error_msg
|
||
|
# Print an error message and exit.
|
||
|
###############################################################################
|
||
|
sub error_msg ($) {
|
||
|
my $err_msg = $_[0];
|
||
|
|
||
|
if (! -z $err_msg) {
|
||
|
print(STDERR "[error] $err_msg.\n");
|
||
|
}
|
||
|
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB print_help
|
||
|
# Print a help message.
|
||
|
###############################################################################
|
||
|
sub print_help () {
|
||
|
print "Usage: $0 <snmptrapd log file>\n";
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB log_msg
|
||
|
# Print a log message.
|
||
|
###############################################################################
|
||
|
sub log_msg ($) {
|
||
|
my $log_msg = $_[0];
|
||
|
|
||
|
if (! -z $log_msg && $Verbose == 1) {
|
||
|
print(STDOUT "[log] $log_msg.\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB load_idx
|
||
|
# Load index file.
|
||
|
###############################################################################
|
||
|
sub load_idx () {
|
||
|
my $line;
|
||
|
my $current_ino;
|
||
|
my $current_size;
|
||
|
|
||
|
log_msg("Loading index file $Idx_file");
|
||
|
|
||
|
open(IDXFILE, $Idx_file) || error_msg("Error opening file $Idx_file: " .
|
||
|
$!);
|
||
|
|
||
|
# Read position and date
|
||
|
$line = <IDXFILE>;
|
||
|
($Idx_pos, $Idx_ino, $Idx_size) = split(' ', $line);
|
||
|
|
||
|
close(IDXFILE);
|
||
|
|
||
|
# Reset the file index if the file has changed
|
||
|
$current_ino = (stat($Log_file))[1];
|
||
|
$current_size = -s "$Log_file";
|
||
|
if ($current_ino != $Idx_ino || $current_size < $Idx_size) {
|
||
|
log_msg("File changed, resetting index");
|
||
|
|
||
|
$Idx_pos = 0;
|
||
|
$Idx_ino = $current_ino;
|
||
|
}
|
||
|
$Idx_size = $current_size;
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB save_idx
|
||
|
# Save index file.
|
||
|
###############################################################################
|
||
|
sub save_idx () {
|
||
|
|
||
|
log_msg("Saving index file $Idx_file");
|
||
|
|
||
|
open(IDXFILE, "> $Idx_file") || error_msg("Error opening file $Idx_file: "
|
||
|
. $!);
|
||
|
print (IDXFILE $Idx_pos . " " . $Idx_ino . " " . $Idx_size);
|
||
|
close(IDXFILE);
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB create_idx
|
||
|
# Create index file.
|
||
|
###############################################################################
|
||
|
sub create_idx () {
|
||
|
my $first_line;
|
||
|
|
||
|
log_msg("Creating index file $Idx_file");
|
||
|
|
||
|
open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " .
|
||
|
$!);
|
||
|
|
||
|
# Go to EOF and save the position
|
||
|
seek(LOGFILE, 0, 2);
|
||
|
$Idx_pos = tell(LOGFILE);
|
||
|
|
||
|
close(LOGFILE);
|
||
|
|
||
|
# Save the file inode number
|
||
|
$Idx_ino = (stat($Log_file))[1];
|
||
|
|
||
|
# Save the index file
|
||
|
save_idx();
|
||
|
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB parse_log
|
||
|
# Parse log file starting from position $Idx_pos.
|
||
|
###############################################################################
|
||
|
sub parse_log () {
|
||
|
my $line;
|
||
|
|
||
|
log_msg("Parsing log file $Log_file");
|
||
|
|
||
|
# Open log file for reading
|
||
|
open(LOGFILE, $Log_file) || error_msg("Error opening file $Log_file: " .
|
||
|
$!);
|
||
|
|
||
|
# Go to starting position.
|
||
|
seek(LOGFILE, $Idx_pos, 0);
|
||
|
|
||
|
# Parse log file
|
||
|
my $data;
|
||
|
|
||
|
# Matched line id
|
||
|
my $matched_line = 0;
|
||
|
|
||
|
$/ = undef;
|
||
|
$data = <LOGFILE>;
|
||
|
|
||
|
$Idx_pos = tell(LOGFILE);
|
||
|
close(LOGFILE);
|
||
|
|
||
|
# Save the index file
|
||
|
save_idx();
|
||
|
|
||
|
return \$data;
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
# SUB parse_log
|
||
|
# Print log data to STDOUT.
|
||
|
###############################################################################
|
||
|
sub print_log ($) {
|
||
|
my $data = shift;
|
||
|
my $zdata;
|
||
|
|
||
|
return unless defined($data) and $$data ne '';
|
||
|
|
||
|
if (!zip($data => \$zdata)) {
|
||
|
error_msg("Compression error: $ZipError");
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
print STDOUT "<trap_data><![CDATA[" . encode_base64($zdata, '') . "]]></trap_data>\n";
|
||
|
}
|
||
|
|
||
|
###############################################################################
|
||
|
###############################################################################
|
||
|
## Main
|
||
|
###############################################################################
|
||
|
###############################################################################
|
||
|
|
||
|
# Check command line parameters
|
||
|
if ($#ARGV < 0) {
|
||
|
print_help();
|
||
|
exit 1;
|
||
|
}
|
||
|
|
||
|
$Log_file = $ARGV[0];
|
||
|
# Create index file storage directory
|
||
|
if ( ! -d $Idx_dir) {
|
||
|
mkdir($Idx_dir) || error_msg("Error creating directory $Idx_dir: "
|
||
|
. $!);
|
||
|
}
|
||
|
|
||
|
# Check that log file exists
|
||
|
if (! -e $Log_file) {
|
||
|
error_msg("File $Log_file does not exist");
|
||
|
}
|
||
|
|
||
|
# Create index file if it does not exist
|
||
|
$Idx_file=$Idx_dir . basename($Log_file) . ".idx";
|
||
|
if (! -e $Idx_file) {
|
||
|
create_idx();
|
||
|
exit 0;
|
||
|
}
|
||
|
|
||
|
# Load index file
|
||
|
load_idx();
|
||
|
|
||
|
# Parse log file
|
||
|
my $data = parse_log();
|
||
|
|
||
|
# Print output to STDOUT
|
||
|
print_log ($data);
|
||
|
|
||
|
exit 0;
|