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/