Paul Kraus wrote:
>
> Problem: Need to create a hash like data structure that contains the key as
> an ip address. The dhcpd leases file contains all leases handed out and the
> time they where assigned using UTC time. Using the epoch time stamp in the
> access file and the ipaddress to get the actual host name of the machine
> that made the request seems to be a harder thing to do then I thought.
>
> I have the following script that seems to work but it just seems like a
> really awful way of doing it.
>
[snip data samples]
>
> use strict;
> use warnings;
> use Date::Simple;
> my ( %users, %ip, %dates );
> open ( DHCP, "<dhcpd-leases.txt" ) or die ("Could not open leases file
> $!\n");
> open ( OUT, ">newlog.txt" ) or die ("Could not open log file for writing $!
> \n");
>
> my ( $ip, $date, $hostname );
> while ( <DHCP> ) {
>   $ip = $1 if ( /lease\s([\d\.]+)/ );
>   $date = $1 if ( /starts\s\d\s([\d\/]+)\s/ );
>   $date =~ s/\//-/g if ($date);
>   $date =~ s/(\d\d\d\d-)(\d)-/${1}0$2/ if ($date);
>   $date =~ s/(\d\d\d\d-)(\d)-/${1}0$2/ if ($date);
>   $date =~ s/(\d\d\d\d-\d\d-)(\d)$/${1}0$2/ if ($date);
> #  print "$date\n";
>   if ( /hostname "(\w+)"/ ){
>     $hostname = $1;
>     push( @{$dates{$ip}}, "$hostname|$date");
>     $users{"$ip-$date"} = $hostname;
>   }
> }
>
> open ( LOG, "<access.txt" ) or die ("Could not open Access Log $!\n" );
> while ( <LOG> ){
>   my ($timestamp,$ip,$size,$site) = (split/\s+/, $_)[0,2,4,6];
>   my @timestamp = (gmtime($timestamp))[2,1,0,4,3,5];
>   my $time = "($timestamp[0]:$timestamp[1]:$timestamp[2])";
>   my $date = ($timestamp[5]+1900) . "-" . ( $timestamp[3]+1 ) . "-" .
> $timestamp[4];
>   my $hostname;
>
>   #lookup host name
>   if ($dates{$ip}){
>     foreach (@{$dates{$ip}}){
>       my @record = split /\|/;
>       $date =~ s/(\d\d\d\d-)(\d-)/${1}0$2/;
>       $date =~ s/(\d\d\d\d-)(\d)-/${1}0$2/;
>       $date =~ s/(\d\d\d\d-\d\d-)(\d)$/${1}0$2/;
> #      print "Two Dates:Squid($date)\tdhcp($record[1])\n";
>       my $squiddate = Date::Simple -> new ($date);
>       my $dhcpddate = Date::Simple -> new ($record[1]);
>
>       if ($squiddate < $dhcpddate){
> $hostname = $record[0];
> last if ($hostname ne $ARGV[0]);
> print OUT "$hostname|$time|$date|$size|$site\n";
> last;
>       }
>     }
>   }
> }

Hi Paul.

This looked like a good puzzle! I think you're on the right lines, although
there's a lot that could be made neater. For instance:

- You're zero-padding the month and day fields twice - both before they're
pushed onto @dates and after they're taken out.

- I would have written the date formatting like this:

  if (/starts/) {
    $date = sprintf '%04d/%02d/%02d', m|(\d+)/(\d+)/(\d+)|;
  }

- It may be better to write

  push @{$dates{$ip}}, "$hostname|$date"

as

  push @{$dates{$ip}}, [$hostname, $date]

so that the two values remain separate and don't need a 'split' to resolve them.

- This is how I'd generate the log time and date in the format you want.

  my @timestamp = (gmtime($timestamp));
  $timestamp[5] += 1900;
  $timestamp[4] += 1;
  my $time = sprintf '%02d:%02d:%02d', @timestamp[2,1,0];
  my $date = sprintf '%04d-%02d-%02d', @timestamp[5,4,3];


- You never read from the %users hash. Do you still need this structure?

- Dates in the format YYYY-MM-DD can be compared with the string operators (lt,
eq, gt etc.) so you don't need Date::Simple.

- Finally I'm not sure about your final test, which drops out at the first DHCP
entry dated after the log date. Surely it should be the last such entry?

HTH for now.

Rob




-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to