I think a simple tell -> seek algorithm and by checking file size == 0 are not enough. Your log file might have been truncated, re-written to, and then the new file size grows bigger than before. If you seek to previous position, then the script will work, but now it has an undetected logic error. You will need to record the position + the last line you have seen, then you can make sure that is the line where you have last visited.

This will work if the log is not a rotating log. What if it is? Uh... my head hurts.

The following is my attempt during my lunch break - (Ok, I have deliberately chose not to use Pod::Usage)
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

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.