On 01/04/2007 09:48 PM, beast wrote:
Hi all,

I have text file which has these following format:

username1:10.0.0.1
username2:10.0.0.3

Basically, it has username with at least 1 IP address.

I would like to parse log which contains IP address but might not contains the username, ie:

10.0.0.1 username1
10.0.0.2 -
etc...

---
while (<LOG>) {
  ($ip, $uname) = split/\s/;
   next if ($uname eq '-');
   print "Warning: $uname logged from IP $ip\n" if ( $db{$uname} ne $ip );
}
---

Now it has a problem because in the db file, 1 username might contains 2 or more IP's and this program will run every 5 mins parsing 1000 lines, so it must be run quickly before the next schedule. Any idea would be appreciated.

--beast


One way to do it might be to use a client-server approach. The server parses and loads the username db once, and the client communcates with the server.

Since the server already has the data loaded, its response should be virtually instantaneous.

Here is some code to think about (Linux-specific, uses FIFO's):

---------userwarn-server.pl-----------
#!/usr/bin/perl

use strict;
use warnings;
use File::Spec::Functions;
use POSIX qw(mkfifo);
use File::Slurp;
use Data::Dumper;
use Fatal qw(open close);
use Hash::Util qw(lock_keys);

our ($CONTINUE, $STOP);
(*CONTINUE, *STOP) = (\1, \0);

my %base = (
    fifodir => '/tmp/userwarn.dir',
    usersdb => 'ulist.txt',
);

unless (-d $base{fifodir}) {
    umask 0;
    mkdir $base{fifodir};
    mkfifo catfile($base{fifodir}, 'in'), 0622;
}

my %users;
%users = map { chomp; split /[: ]+/,$_,2; }
    read_file($base{usersdb});
$_ = { map { $_ => 1 } split } for values %users;
lock_keys(%users);

while (session()) {
}

cleanup();
exit;

################################


sub cleanup {
    return unless -d $base{fifodir};
    unlink catfile($base{fifodir}, 'in');
    unlink catfile($base{fifodir}, 'out');
    rmdir $base{fifodir};
}

sub session {
    my %logged;
    my @warn;
    print "START SESSION\n";
    open my $fin, '<', catfile($base{fifodir},'in');

    while (my $line = <$fin>) {
        if ($line =~ /^EXIT$/) {
            close $fin;
            return $STOP;
        }
        if ($line =~ /^\s*([\d.]+) +(\S+)\s*$/) {
            my ($user, $ip) = ($2,$1);
            $logged{$user} = $ip;
        }
    }

    while (my ($user, $ip) = each %logged) {
        unless ($users{$user}->{$ip}) {
            push @warn, "Warning: $user logged in from $ip\n";
        }
    }

    write_file catfile($base{fifodir},'out'), @warn;
    system(cat => catfile($base{fifodir},'out'));

    close $fin;
    $CONTINUE;
}


-----------------userwarn-client.pl:--------------
#!/usr/bin/perl

use strict;
use warnings;
use File::Slurp;
use File::Spec::Functions;

my $outdata = '
10.0.0.1 alice
10.0.0.29 morgan
10.0.0.21 mark
10.0.0.38 jonas
';

my %base = (
    fifodir => '/tmp/userwarn.dir',
);

write_file(catfile($base{fifodir},'in'), $outdata);
sleep 1;
system(cat => catfile($base{fifodir},'out'));

----------------ulist.txt------------
alice:10.0.0.1
morgan:10.0.0.2 10.0.0.29
jonas:10.0.0.3
mark:10.0.0.4 10.0.0.13
larry:10.0.0.5

---------------end------------

In the real world, userwarn-client.pl would grab its data from the logfile; however, I was too bored with that part to create a mock logfile.


HTH



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


Reply via email to