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

me = /s27 (lost my passwort) my problem: i have tor read a logfile, while it is being written. the logfile grows very slowly, logging special http-requests from the browser, while the user surfs around in the internet. i'm doing it with the following code, but my cpu-usage goes near 100% because of the always present while-loop - well, you'll see:
$stop == 0; # always stays 0 open (MUFFINLOG,"<muffin.log") || die "Muffin.log nicht gefunden\n"; while($stop == 0) { while(<MUFFINLOG>) { chomp; if($_ ne "") { push(@Zeile,$_); &ZeilenAnalyse # some analyse and printing } } print "DID IT\n"; # for testing purpose only }
sorry about the german variable, but i guess you get the idea. is there a way, to only read a line, when there is a new line??

Replies are listed 'Best First'.
Re: Reading line from file only when there is a new line (live)
by Corion (Patriarch) on Sep 12, 2001 at 16:59 UTC

    You want to take a look at File::Tail, which implements methods to follow a file.

    The documentation mentions several ways how you can use the filehandle returned by File::Tail, you can either use it as an IO handle, complete with select() support, or use the read() method, which tries to have near 0% CPU usage and will return whenever a new line is available.

Re: Reading line from file only when there is a new line (live)
by blakem (Monsignor) on Sep 12, 2001 at 17:01 UTC
Re: Reading line from file only when there is a new line (live)
by davorg (Chancellor) on Sep 12, 2001 at 16:59 UTC

    Why not take a slightly different approach. Constantly read the file, but only process complete lines. Something like this:

    my $buff; my $data; while (1) { if (read(MUFFINLOG, $buf, 1024)) { $data .= $buf; while ($data =~ /\n/) { my $line; ($line, $data) = split /\n/, $data, 2; # process the line of data that is in $line } } }
    --
    <http://www.dave.org.uk>

    Perl Training in the UK <http://www.iterative-software.com>

      I believe you need a seek( MUFFINLOG, 0, 1 ); in there to reset the eof... otherwise you won't get newly appended data...

                      - Ant
                      - Some of my best work - Fish Dinner

        me = /s27 ... i get the newly appended data (don't know why ;) - i think i'll use the TAIL thing... sounds good to me. thx alot for all the support.
Re: Reading a line from file only when there is a new line (live)
by Caillte (Friar) on Sep 12, 2001 at 17:07 UTC

    A simple method is to use IO::Select to watch over the handle. The example below watches STDIN and waits for 5 seconds for a read before passing on.

    By playing with parameters you can change the wait time, or make the code wait permanently. Also, by using IO::Handle or the like, you can read in individual characters, instead of whole lines.

    #!/usr/bin/perl use IO::Select; my $select = IO::Select->new(); $select->add(\*STDIN); my @ready; while(1) { if(@ready = $select->can_read(5)) { foreach (@ready) { my $line = <$_>; print "Read $line\n"; } } else { print "5 seconds passed without a read\n"; } }

    $japh->{'Caillte'} = $me;

Re: Reading line from file only when there is a new line (live)
by George_Sherston (Vicar) on Sep 12, 2001 at 17:36 UTC
    I'd guess you've thought of this already, but would it be possible to do
    push(@Zeile,$_); &ZeilenAnalyse; # and other related code
    inside the script which writes to the log file in the first place? Then you don't need the while loop at all, and more importantly you don't need the repeated open which is presumably what's taking up cpu space.

    If that doesn't work, I'd have thought the quick and dirty solution was a sleep n in the while loop so that the open only happens every n seconds, rather than continually.

    § George Sherston