onegative has asked for the wisdom of the Perl Monks concerning the following question:

Howdy, I am attempting to use a continous for() loop while reading a log file. I then use tell() and seek() to re-establish the last known position within the log file. I works (kinda), but I keep losing my first entry of the log. That is from the first moment it opens the log or if I cat additional information to the log, the first new entry is dropped. Can anyone explain what could be happening. Below is a sample of the code I am using. I have tried different WHENCE values on the seek which doesn't help. And if I drop the for() loop and just print the FH it does print all entries of the log, thus the dropping of the first entry is clearly asscoiated with the loop, but I can not understand where it is going. Thanks for all help, Danny.
#!/usr/bin/perl # # # $LogFile="/usr/local/apache2/eventmgr/ncomount/page.log"; $naptime=3; #Reads LOGFILE continuously open(LOGFILE,"<$LogFile") || die "Couldn't open file Status - $!\n"; for (;;) { for ($logpos = tell(LOGFILE); <LOGFILE>; $logpos = tell(LOGFILE)) { while(<LOGFILE>){ print; } sleep $naptime; seek(LOGFILE, $logpos, 0); # seek to last known } }

20040225 Edit by BazB: Changed title from 'Where did it go???'

Replies are listed 'Best First'.
Re: Losing first entry of Apache log
by Enlil (Parson) on Feb 25, 2004 at 18:00 UTC
    I would guess that in the for loop when you call <LOGFILE>; it grabs a line, and then grabs a new line in the while loop.
    for ($logpos = tell(LOGFILE); <LOGFILE>; . . .#here while (<LOGFILE>) { #and here
    So everytime it hits the inside for loop it grabs two lines before it prints one (and only prints the latter). There is File::Tail for this sort of thing though.

    -enlil

      I was testing that theory and it is in fact what is happening. The modified code below works and does not drop the first entry... also a bit easier to read. I would reccomend using while(1) for continous loops.

      #!/usr/bin/perl -w use strict; my $LogFile="C:/test.txt"; my $naptime=3; my $logpos; #Reads LOGFILE continuously open(LOGFILE,"<$LogFile") || die "Couldn't open file Status - $!\n"; while (1) { sleep $naptime; $logpos = tell(LOGFILE); while(<LOGFILE>) { print; } seek(LOGFILE, $logpos, 0); # seek to last known }

      <edit>the more I thought about it you don't even need the $logpos variable. Just use seek(LOGFILE,0,0) to seek to the beginning,since it seemed like what you wanted to do. Although if you have a specific point in the file you want to start reading from then you will need to predefine it and even then you still wouldn't need the call to tell(LOGFILE) I believe</edit>

      Hope this helps.

      Grygonos