Rob Oravec wrote:
> Hi All!

Hello,

> Please help this beginner!
> More than likely there is an easy way to do this and/or I am doing
> something stupid but I just don't know how.
> Sorry if this is a bit long.
> 
> (Scenario)
> -Several routers/firewalls log events to a single ($log_file).
> -I want to be able to seperate the logs based on router/firewall IP
> addresses ($log_source) and dump all
> matches to their relevant files for further processing ($date-$ip.log)
> -Process the ($ip_file) line by line using each line as a regular
> expression, processing the ($log_file).
> This way if I add more routers/firewalls to the picture then its just a
> case of adding a new IP address to the ($ip_file) and not adding regular
> expressions to the script.
> 
> ($ip_file)
> 10.10.10.1
> 10.10.10.2
> 10.10.10.3
> 
> ($log_file)
> <snipped>
> 2005-09-05 00:05:11    Local5.Info    10.10.10.1    %SEC-6-IPACCESSLOGP:
> list IN_REF_2 denied tcp xxx.xxx.xxx.xxx(2948) -> xxx.xxx.xxx.xxx(135),
> 1 packet
> 2005-09-05 00:05:11    Local5.Info    10.10.10.2    %SEC-6-IPACCESSLOGP:
> list IN_REF_2 denied tcp xxx.xxx.xxx.xxx(2949) -> xxx.xxx.xxx.xxx(135),
> 1 packet
> 2005-09-05 00:05:11    Local5.Info    10.10.10.3    %SEC-6-IPACCESSLOGP:
> list IN_REF_2 denied tcp xxx.xxx.xxx.xxx(2973) -> xxx.xxx.xxx.xxx(135),
> 1 packet
> 
> My result/problem so far:
> I think I read the ($ip_file) correctly and then open the ($log_file) to
> search through it based on each line in the ($ip_file).
> When it has processed the ($log_file) and dumped the results to the
> relavant files ($date-$ip.log) it only prints out the last matching line
> for each ($log_source) but need it to print all the matches.
> 
> ------------------------------------------------------------start-script
> #!/usr/bin/perl

Your next two lines should be:

use warnings;
use strict;


They will help you find mistakes and will enforce better programming habits.


> ($mday,$mon,$year) = (localtime)[3..5];
> $date = sprintf "%d%02d%02d", $year+1900, $mon+1, $mday;
> ($sec,$min,$hour)=localtime(time);
> $time = sprintf "%02d:%02d:%02d", $hour, $min, $sec;

Why not just make *one* call to localtime() to get all the fields you need?

my ( $sec, $min, $hour, $mday, $mon, $year ) = localtime;
my $date = sprintf '%04d%02d%02d', $year + 1900, $mon + 1, $mday;
my $time = sprintf '%02d:%02d:%02d', $hour, $min, $sec;


> $log_dir = "/home/net1/log";
> $rep_dir = "/home/net1/Apache2/htdocs/router-logs";
> $log_file = "$log_dir/$date.log";
> $ip_file = "/home/net1/log/ip.txt";
> 
> open(IPFILE, "$ip_file") || die "Could not open $ip_file";

There is no need to put quotes around $ip_file as it is already a string.  You
should include the $! variable in the error message so you know *why* the file
would not open.

open IPFILE, $ip_file or die "Could not open $ip_file: $!";


> foreach (<IPFILE>) {

You are reading the entire file into a list in memory and each subsequent line
is assigned to the $_ variable.


>            @lines = <IPFILE>;

The filehandle IPFILE is now at end-of-file so it assigns nothing to @lines.


>            chomp($ip);

You are chomping the $ip variable which has nothing in it the first time
through the loop and the previous line's contents for each subsequent iteration.


>            ($ip) = split;  

This is short for:

           ($ip) = split ' ', $_, 2;

Which means that you are actually getting the data from $ip_file into the $ip
variable.


> open (LOGFILE, $log_file) || die "Could not open $log_file";

Because you are inside a foreach loop you have to open this file for every
entry in $ip_file, that could really slow down your program if $log_file is
large.  You should include the $! variable in the error message so you know
*why* the file would not open.


> while (<LOGFILE>) {   ($datestamp, $timestamp, $facility, $log_source,
> $restofline) = split (/\s+/, $_);

You used split() correctly before, why the change here?  Your variable
$restofline implies that it will contain the rest of the line after
$log_source but that is incorrect, it will contain the next *field* after
$log_source.  To get the rest of the line into $restofline you have to use the
third argument to split().


> if ($log_source    =~ /$ip/) {

This won't work correctly because $ip contains regular expression
meta-characters, specifically the . character which matches any character
(except newline.)  You need to either use the quotemeta escape:

if ($log_source =~ /\Q$ip/) {

Or just test for equality:

if ($log_source eq $ip) {


>            $log_new = "$rep_dir/$date-$ip.log";              open(OUT,
> ">$log_new") || die "Could not open log_file";                  print OUT;

You are opening $log_new for output which truncates the file to zero length.
You should include the $! variable in the error message so you know *why* the
file would not open.


>            close(OUT);
>            print;
>            }               }
> }           close(IPFILE);
> close(LOGFILE);
> ------------------------------------------------------------stop-script
> Comment/s:
> The search has to be against the ($log_source) variable as the IP
> address may appear more than once in the same line and meaning something
> completely different.
> 
> Other things I have tried:
> I have tried using the append option when opening ($log_new) and works
> great on the first go, then obviously it appends the next go round.

I don't understand why you are saying that the append option does not work
correctly.  What exactly are you trying to accomplish?



John
-- 
use Perl;
program
fulfillment

-- 
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