Quoth Andy <>:
> Greets 
>
> Q; I am trying to learn how to define some variables
>
> The basis of this script is to Scrub log files for ftp logins,
> seperate the successful logins
>
> Then create an array ( I hope the right terminology) to seperate it
>
> I hardcoded the log file, because I am looking for a way for it to
> scrub *.logs on a server
>
> but ...hey step by step right.
>
> Fields: date time c-ip cs-username cs-method cs-uri-stem sc-status sc-
> bytes cs-host
> 2008-01-20 00:00:02 x.x.x.x 0598_Andy [6952041]sent /
> 0598_Andy/qff0598.zip 226 0 -
What are these fields separated by? A single space? Can the fields ever
contain spaces? How are they quoted in that case? What about newlines?
> This field 226 0 - is a successful login
>
> My plan is to scrub the logs, export to file.
>
> sort fields into variable.
>
> I hope in the end to get
>
> 1..log of successful logins
> 2.log of last successful login ( I think I am going to try date
> comparison from most recent to last.)
> 3 be able to parse the fields and get data.
>
>
> I know that there are those of you who are advanced, I would
> appreciate any directions or help.
>
> Again I am trying to put this together this is what I have so far.
>
> #!/usr/bin/perl
> use strict;
> use warnings;
>
> open(INPUT, '<', "ex080120.log")or die("Could not open log file.");
> open(OUTPUT, '>',"ftpacct.log")or die("Could not open log file.");
3-arg open: good.
Checking the return value: good.
It's better to keep filehandles in variables than use the old-fashioned
global handles, though; and if the open fails you should say what
failed, and why:
open(my $INPUT, '<', "ex080120.log")
or die("can't read ex080120.log: $!");
open(my $OUTPUT, '>', "ftpacct.log")
or die("can't write ftpacct.log: $!);
> my $extractedLine;
> while (<INPUT>) {
> my $line = $_;
This is silly. If you want the line in $line, put it there in the first
place:
while (my $line = <$INPUT>) {
> if ($line =~ m/^(.+226\s+0\s+-\s+.*)$/) {
> print OUTPUT "$1\n";
> }
I would recommend splitting the line into a hash first, and then
selecting lines based on that. Something like
my @fields = qw/
date time c_ip
cs_username cs_method cs_uri_stem
sc_status sc_bytes cs_host
/;
while (my $line = <$INPUT>) {
# Here I assume fields are delimited by a single space, and
# spaces and newlines *never* appear in a field (not even inside
# quotes). If this isn't true, you probably want to use the
# Text::CSV_XS module, which can parse all sorts of
# <foo>-delimited files.
my %record;
@record{@fields} = split / /, $line;
$record{sc_status} == 226
and $record{sc_bytes} == 0
and $record{cs_host} eq '-'
or next;
print $OUTPUT $line;
}
Once you've understood that bit of code it should be straightforward to
change it to do something more sophisticated. To keep track of the last
login for any given user, you need a hash %lastlogin, keyed by username,
that lives outside the loop.
> }
> close(INPUT);
> close(OUTPUT);
An advantage of keeping filehandles in variables is that they are closed
for you when the variable goes out of scope. An advantage of real
operating systems (Win32 counts, here) is that they close filehandles
for you when the process exits, in any case.
That said, there is value in explicitly closing a filehandle opened for
writing, *and checking the return value*. If any of the writes to that
filehandle failed (disk full, for instance) the error will be returned
by close. (Of course, if you want to catch errors sooner than that, you
can check the return value of print instead.)
> exit;
There's no need to explicitly exit from a Perl program. Falling off the
end is the usual way to finish.
Ben
--
I've seen things you people wouldn't believe: attack ships on fire off
the shoulder of Orion; I watched C-beams glitter in the dark near the
Tannhauser Gate. All these moments will be lost, in time, like tears in rain.
Time to die.