views:

59

answers:

3

I have a perl script that is only keeping the last set of records for a named set and I have more than one set of records. So its over writing the data in the hash and just keeping the last set. I need help in printing out all the records. Thanks!

Here's a copy of my script:

#!/usr/local/bin/perl 

use strict;
use warnings;
use Data::Dumper;

my ($ServerName)=@ARGV;
my %MyItems;
foreach my $ServerName(@ARGV){
   while (my $line = <>){
     chomp $line;
              if ($line =~ m/.* \w+ \d{2} (\d{2}:\d{2}:\d{2}) \d{4}: ([^:]+):backup:/){
                  my $ServerName = basename $ARGV, '.mydomain.com.backup-software.log'; #$ARGV is reading input from command line
                  my $BckupSet =$2;
                  my $BckupVal=$1;
                  $MyItems{$ServerName}{$BckupSet}->{'1-Server'}    = $ServerName;
                  $MyItems{$ServerName}{$BckupSet}->{'2-BackupSet'} = $BckupSet;
                  $MyItems{$ServerName}{$BckupSet}->{'3-StartTime'} = $BckupVal;

                  if ($line =~ m/(backup-date)[:=](.+)/){
                      my $BckupKey="4-DateStamp";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }

                  if ($line =~ m/(backup-time)[:=](.+)/){
                      my $BckupKey="5-Duration";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(backup-size)[:=](.+)/){
                      my $BckupKey="6-Size";
                      my $BckupVal=$2;
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(Backup succeeded)/){
                      my $BckupKey="7-Status";
                      my $BckupVal="Succeeded";
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                  }
                  if ($line =~ m/(ERROR)[:=](.+)/){
                      my $BckupKey="8-Status";
                      my $BckupVal="Unsuccessful";
                      $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
                      print "$BckupKey=$BckupVal\n" if debug;
                  }
              }
   } #endwhile
   print Dumper(\%MyItems);
   for my $ServerName(keys%MyItems){
     for my $BckupSet(keys%{$MyItems{$ServerName}}){
       for(sort keys%{$MyItems{$ServerName}{$BckupSet}}){
         #print$_,'=>',$MyItems{$ServerName}{$BckupSet}{$_},';';
         print$_,'=',$MyItems{$ServerName}{$BckupSet}{$_},';';
       }
       print"\n";
     }
   }
} #END foreach

Here's what it looks like when it dumps:

$VAR1 = {
          'server1.name.colo' => { 
                                        'set1' => {
                                                               '3-StartTime' => '07:08:15',
                                                               '1-Server' => 'server1.name.colo',
                                                               '6-Size' => '72.04 GB',
                                                               '7-Status' => 'Succeeded',
                                                               '4-DateStamp' => '20100820060002',
                                                               '5-Duration' => '01:08:13',
                                                               '2-BackupSet' => 'set1',
                                                               '8-Status' => 'Unsuccessful'
                                                             },
                                        'set2' => {
                                                                '7-Status' => 'Succeeded',
                                                                '6-Size' => '187.24 GB',
                                                                '3-StartTime' => '01:51:25',
                                                                '4-DateStamp' => '20100820000003',
                                                                '1-Server' => 'server1.name.colo',
                                                                '5-Duration' => '01:51:21',
                                                                '2-BackupSet' => 'set2'
                                                              },
                                        'set3' => {
                                                              '3-StartTime' => '23:00:05',
                                                              '4-DateStamp' => '20100814230003',
                                                              '1-Server' => 'server1.name.colo',
                                                              '8-Status' => 'Unsuccessful',
                                                              '2-BackupSet' => 'set3'
                                                            },
                                        'set4' => {
                                                              '7-Status' => 'Succeeded',
                                                              '6-Size' => '427.75 GB',
                                                              '3-StartTime' => '00:43:20',
                                                              '4-DateStamp' => '20100819200004',
                                                              '1-Server' => 'server1.name.colo',
                                                              '5-Duration' => '04:43:14',
                                                              '2-BackupSet' => 'set4'
                                                            },
                                        'set3' => {
                                                              '7-Status' => 'Succeeded',
                                                              '6-Size' => '46.42 GB',
                                                              '3-StartTime' => '04:42:59',
                                                              '4-DateStamp' => '20100820040002',
                                                              '1-Server' => 'server1.name.colo',
                                                              '5-Duration' => '00:42:56',
                                                              '2-BackupSet' => 'set3'
                                                            }
                                      }
        };
A: 

What do you expect $ARGV to be?

reinierpost
$ARGV is a logfile. i'm looping more than 1 logfile in from other servers. I am just testing now one just one logfile and there are a number of entries there that I am missing. I am basically seeing the last set of data towards the end of the log..
jda6one9
Questions for clarification go into the comment box, not in the answer box.
daxim
The point is that both the foreach loop and $ServerName variable and the while(<>) and $ARGV both loop over the values in @ARGV - you want a single loop there.
reinierpost
+2  A: 

Based on the debug output, it looks like your problem is here:

if ($line =~ m/(ERROR)[:=](.+)/){
    my $BckupKey="8-Status";
    my $BckupVal="Unsuccessful";
    $MyItems{$ServerName}{$BckupSet}->{$BckupKey} = $BckupVal;
    print "$BckupKey=$BckupVal\n" if debug;
}

To save all errors, you'll need to treat that hash slot as a reference to an array:

if ($line =~ m/(ERROR)[:=](.+)/){
    my $BckupKey="8-Status";
    my $BckupVal="Unsuccessful";
    push @{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} } => $BckupVal;
    print "$BckupKey=$BckupVal\n" if debug;
}

In your dump, the 8-Status values will resemble

'8-Status' => [ 'Unsuccessful', 'Other error', 'Et cetera' ],

If you want to loop over them later, you'd do something like

foreach my $err (@{ $MyItems{$ServerName}{$BckupSet}{$BckupKey} }) {
    print "got $err\n";
}

To get only the first, you'd write

print $MyItems{$ServerName}{$BckupSet}{$BckupKey}[0], "\n";

Another issue is

foreach my $ServerName(@ARGV){
   while (my $line = <>){

Realize that while (<>) { ... } implicitly loops over all files named in @ARGV, so nesting it inside a loop over @ARGV doesn't quite make sense. If your command line is of the form

$ readlogs server1 server2 server3 log1 log2

then you'd want to first remove from @ARGV the servers using shift. Distinguishing arguments the user intends as server hostnames could be tricky. One convention is using -- to signal the end of option processing, so you might

my @servers;
while (@ARGV) {
  my $server = shift;
  last if $server eq "--"
  push @servers => $server;
}

die "Usage: $0 server .. -- log ..\n" unless @ARGV;

while (<>) {
  # ...
}
Greg Bacon
@gbacon - thank you. would i apply the push to all my other if conditions as well? printing the keys too?
jda6one9
@jda6one9 Using `push` for all of them would work, but you may get annoyed with one-element arrays. Doing it this way has the advantage of never throwing away data, but it may be too permissive for what you want to do.
Greg Bacon
@gbacon - you helped me earlier with using this --> xargs -I{} ./myscript.pl {} <prodlogs.txt Where 'prodlogs.txt' is a list of all there server logs I need to scan. Anyways, i will definitely take note of your input. thanks again.
jda6one9
@jda6one9 You're welcome. I'm glad it helps.
Greg Bacon
+2  A: 

This is off topic, but any time you need deeply nested data structures your code runs a risk of becoming bloated and hard to read. Simple convenience variables go a long way toward streamlining things and relieving the reader of the code (you, 3 months from now) of having to perform many mental diffs:

# A convenience var.
my $bs = $MyItems{$ServerName}{$BckupSet};

# The rest of your code can use the var.
$bs->{'1-Server'} = $ServerName;

Also, you've got several if blocks that do basically the same thing. Seems amenable to some sort of dispatch table strategy:

my @dispatch_table = (
    {
        regex => qr/(backup-date)[:=](.+)/,
        key   => '4-DateStamp',
        val   => sub { $2 },
    },
    {
        # etc.
    },
);

Then your if blocks boil down to something like this:

for my $dt (@dispatch_table){
    next unless $line =~ $dt->{regex};
    $bs->{ $dt->{key} } = $dt->{val}->();
}
FM
@FM - thanks for the tips! I've basically learned perl in the last few weeks. So, I'll take what I can get as far as learning.
jda6one9