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

Hi All I am still trying to create a script to tail a log file and report on an instant or exception when a message is not recieved. This means I will be searching for a string in a log file which is constant meaning what ever is writing to the log file does this all the time. Now if I don't recieve a message from whatever is writing to the log within 60 seconds I would like to create a exception error e.g ( print STDERR "Have not recieved a message in the last 60 seconds"; ) I am finding creating this exception timer part the difficult bit. I have attached my code below and would like some advice on if I am on the right track. Any assistance would be much appreciated. Kind Regards James
use IO::Select; $select = IO::Select->new(); # repeat next two lines for all filehandles to poll open(LOGFILE, "< james.log") || die; seek(LOGFILE, 0, 2); $select->add(*LOGFILE); for (;;) { if (@ready = $select->can_read) { # input waiting on the filehandles in @ready foreach $filehandle (@ready) { while (<$filehandle>) { chomp(); if (m/^Hello/) { print STDERR "This is a hello msg"; $starttime = time; } } } sleep 2; $endtime = time; print STDERR "$starttime\n"; print STDERR "$endtime\n"; } } $timediff = $endtime - $starttime; if ( $timediff = "60" ) { print STDERR "Have not recieved a message in the last + $timediff seconds"; }

Replies are listed 'Best First'.
Re: Log file tailing
by matija (Priest) on May 17, 2004 at 09:27 UTC
    Doing select for ordinary files won't do you any good. Disk files (as opposed to sockets and pipes) are always "ready for reading".

    I suggest you look at the code for File::Tail. While I never wrote any hooks to tell the calling program when there was no traffic in the file, I do handle it internaly and you could add it to the code fairly easily.

    Send me a patch once it's done, and if it's fairly clean, I'll include it in the next release. (Note, I suggest a callback for implementing that).

      Hi

      Unfortunatly, Im very new to perl and just starting out, so I would not know how to write a patch for the File::Tail module. Maybe you can help me implement this ??

      Kind Regards James
Re: Log file tailing
by rinceWind (Monsignor) on May 17, 2004 at 09:54 UTC
    I use a different approach than IO::Select when solving this type of problem. Operating systems maintain an end of file marker, which determines how much of the file is readable by another process - the size of the file in bytes.

    My approach is as follows (pseudocode):

    while (1) { stat the file if size of file changed since last time { open file seek to previous EOF print file contents until EOF save EOF position for next time close the file } sleep for x seconds }
    Hope this helps

    --
    I'm Not Just Another Perl Hacker

      Well, that is essentialy what File::Tail does. Except that File::Tail also adjusts the "sleep for x seconds" duration after every read to account for how "busy" the file is: it checks the more frequently updated files more often, and the less frequently updated files less often.

      It also checks for files that have suddenly become shorter (as when a sysadmin does a cat /dev/null >logfile in order to free space), and if the file has not been written for a long time, it closes and reopens it - thus hopefully catching cases where the file has been renamed during a log rotation.

Re: Log file tailing
by ysth (Canon) on May 17, 2004 at 08:41 UTC
    Barely glanced at it, but surely you mean "if ( $timediff >= 60 ) {"?
      Yes, I ment to put that back in in James
Re: Log file tailing
by McMahon (Chaplain) on May 17, 2004 at 15:26 UTC
    James Bach has a link to a Perl program that does what you're doing here in the "TESTING THROUGH AUDIBILITY" entry. It's a neat piece of code, might give you some ideas.
Re: Log file tailing
by tachyon (Chancellor) on May 18, 2004 at 04:38 UTC

    Why not just open a pipe to tail: open F, "|tail -f somefile" or just use File::Tail

    cheers

    tachyon