use strict; use Getopt::Long; use IO::File; use Data::Dumper; GetOptions ( 'i|input=s' => \( my $INPUT = "./access.log" ), 'l|lastpos=s' => \( my $LASTPOS = "./lastpos.txt" ), 'f|feedback' => \( my $FEEDBACK = undef ), ); unless ( defined $INPUT && defined $LASTPOS ) { print <<EOF; Logfile Parser - Parse input log efficiently Usage: $0 [option] Options: -i|--input [filename] Specify the input log file name. -l|--lastpos [filename] Specify the name of last pos file. -f|--feedback Let the program print progress prompt. EOF exit(1); } # load the last pos information my $lastinfo; $lastinfo = ReadLastPosFile($LASTPOS) if -f $LASTPOS; print "Last position:\n", Dumper($lastinfo) if ($FEEDBACK); # verify the log file my $begin_pos = VerifyLastPosition($INPUT, $lastinfo); # process the log file my $f = new IO::File $INPUT, "r" or die "Could not open log file"; if ($begin_pos == -1) { die "Log file has not been changed since last run"; } else { seek $f, $begin_pos, 0; # seek to start of next line } my $next_pos = $begin_pos; my $next_line; while ($next_line = <$f>) { $begin_pos = $next_pos; $next_pos = tell; # process the log file here chomp($next_line); print "$next_line\n"; } # at here, begin pos is the position of the last line seek $f, $begin_pos, 0; chomp($next_line = <$f>); $lastinfo->{pos} = $begin_pos; $lastinfo->{text} = $next_line; print "Last Pos Info:\n", Dumper($lastinfo) if ($FEEDBACK); # ok, write the last info back to file WriteLastPosFile($LASTPOS, $lastinfo); exit(0); sub ReadLastPosFile { # last pos file format - <pos>|<last-line-seen> my $filename = shift; my $f = new IO::File $filename, "r" or die "Could not open lastpos file"; chomp(my $info = <$f>); my %lastinfo; ($lastinfo{pos}, $lastinfo{text}) = $info =~ /(\d+)\|(.*)/; return \%lastinfo; } sub WriteLastPosFile { my ($filename, $lastinfo) = @_; my $f = new IO::File $filename, "w" or die "Could not write to lastpos file"; printf $f "%s|%s\n", $lastinfo->{pos}, $lastinfo->{text}; } sub VerifyLastPosition { my ($logfile, $lastinfo) = @_; my $f = new IO::File $logfile, "r" or die "Could not open log file +"; seek $f, 0, 2; # seek to the end of the file my $eof = tell $f; return 0 if $lastinfo->{pos} >= $eof; # ok, file has been trimmed seek $f, $lastinfo->{pos}, 0; chomp(my $line = <$f>); # retrieve what we believe was the last li +ne return 0 if $line ne $lastinfo->{text}; # ok, file has been trimme +d my $begin_pos = tell $f; # otherwise start from next line # -1 means the file has not been changed since # last time it was parsed. return $eof == $begin_pos ? -1 : $begin_pos; }
In reply to Re: Opening a file at a designated offset based on closing of the file
by Roger
in thread Opening a file at a designated offset based on closing of the file
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |