pramone has asked for the wisdom of the Perl Monks concerning the following question:

Hello perlmonks. I currently have an ugly script that is comparing two logfiles and using a config file to check if the error in the config file exist in the logfile and report the error if there is a difference.

This script is being used on a windows box using Active Perl.

My problem is that I need for the two files to compare, if they are different is the difference because of an error. If it is, does that error match what is in the config file. Currently the way the script is written it will compare the files and return an error if the files are different, but it spits out every alert including those from a previous run. Please excuse the mess, going to clean it up after the initial requirements are met.

#!/usr/bin/perl use warnings; use strict; use File::Compare; use FileHandle; use File::Stat; use File::Copy; my $config = 'C:\NSClient++\scripts\check_logfiles.cfg'; my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = loc +altime(time); my $time_now = sprintf("%02d%02d", $hour,$min); my @errors = (); my $return = 0; if (-e $config) { check_files(); if ( scalar(@errors) gt 0 ) { print join(", ", @errors); $return = 2; } elsif ( scalar(@errors) eq 0 ) { print "No problems detected"; $return = 0; } else { print "This should never happen"; $return = 3; } } else { print "Config file: $config does not exist!\n"; $return = 2; } #sub dates_match # Main sub check_files{ open (CFG, "<", "$config") or die "Can't open config ($config) file: $ +!"; while(<CFG>) { next if /^#/; # Skip comments next if /^\s*$/; # Skip blank lines my ($start_time, $end_time, $start_day, $end_day, $drive, +$fpath, $fname, $error) = split /:/; chomp ($error); if (($time_now >= $start_time && $time_now <= $end_time) & +& ($wday >= $start_day && $wday <= $end_day)) { my $filename = "$drive:". "$fpath". "\\". "$fname"; my $file2 = $filename.".2"; my $count = 0; #print "hello $error"; if ( File::Compare::compare_text($filename, $file2) == + 1){ open (LOG, "<", "$filename") or die "Can't open ($ +filename) file: $!"; while(<LOG>) { chomp; if (/$error/) { # does the error exist push (@errors, "$error"); copy ("$filename","$file2") or die "Copy f +ailed: $!"; } } close(LOG); } elsif ( File::Compare::compare_text($filename, $file2) + == 0){ } copy ("$filename","$file2") or die "Copy failed: $!"; } #use File::Copy; } close (CFG); }

Replies are listed 'Best First'.
Re: Logfile checking
by jwkrahn (Abbot) on Aug 17, 2010 at 02:37 UTC
    if ( scalar(@errors) gt 0 ) { } elsif ( scalar(@errors) eq 0 ) {

    You are using text comparison on numerical values when you should be using numerical comparison.    Note that "0,0" does not equal "0" while 0.0 does equal 0.

    if ( @errors > 0 ) { } elsif ( @errors == 0 ) {

    open (CFG, "<", "$config") or die "Can't open config ($config) file: $ +!"; my $filename = "$drive:". "$fpath". "\\". "$fname"; copy ("$filename","$file2") or die "Copy f +ailed: $!"; copy ("$filename","$file2") or die "Copy failed: $!";

    What's wrong with always quoting "$vars"?

Re: Logfile checking
by Generoso (Prior) on Aug 16, 2010 at 20:59 UTC

    Can you provide sample data of the files that you are comparing. This will help us understand better what you are trying to do.

      I have created test logfiles that just have random messages with one or two that match the string in the config file. Currently I have a test config file that looks like such:
      #format is:- # # #time_start:time_end:day_start:day_end:drive:path:filename:error 0000:2300:1:5:C:Temp:test.server.net.log:No messages have been receiv +ed from the remote host for the specified time period.
      So the logfile has random strings and then a string that matches above.

        Barebones approach that you can extrapolate into what you're looking for:

        #!/usr/bin/perl -w use strict; open my $config, "config.cfg" or die "config.cfg: $!\n"; # Assuming the config file structure is one error per line my %errlist = map { chomp; $_ => 1 } <$config>; close $config; open my $log, "logfile.txt" or die "logfile.txt: $!\n"; while (<$log>){ chomp; /:([^:]+)$/; print "Error '$1' found on line $.\n" if exists $errlist{$1}; }

        In other words, you use the hash to store all your "valid errors", then check the actual errors against that hash. Fairly common algorithm, certainly in Perl.


        --
        "Language shapes the way we think, and determines what we can think about."
        -- B. L. Whorf