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

Hello Monks, I guess I am blind and/or stupid. Why is my FH not being printed to in the below snipet of code? Does anyone see something obvious? Thanks in Advance. Danny
#! /usr/bin/perl # $myfile="whatever.log"; open(REPORT,">$myfile") || die "Couldn't open $myfile: $!\n"; while(1){ $roll = int(rand 6) + 1; $now_string = localtime; if($roll =~ /[1]/){ print REPORT "$now_string: Table XYZ has an invalid archive se +tting.\n"; } if($roll =~ /[2]/){ print REPORT "$now_string: Invalid Login is being attempted, p +lease investigate.\n"; } if($roll =~ /[3]/){ print REPORT "$now_string: Someone has just issued a incorrect + command.\n"; } if($roll =~ /[4]/){ print REPORT "$now_string: Why does this system not like me?\n +"; } if($roll =~ /[5]/){ print REPORT "$now_string: Where in the world is Carmen San Di +ego?\n"; } if($roll =~ /[6]/){ print REPORT "$now_string: Wayne and Thomas are my friends!\n" +; } sleep(30); }

Replies are listed 'Best First'.
Re: Filehandle Print
by ikegami (Pope) on Jan 26, 2005 at 17:31 UTC

    The output is being buffered, so it'll write out a whole bunch of prints at a time, eventually. The following will cause the filehandle to autoflush:

    { my $old_selected_fh = select(*REPORT); $| = 1; select($old_selected_fh); }
Re: Filehandle Print
by runrig (Abbot) on Jan 26, 2005 at 17:31 UTC
    My guess is that the buffer has not yet been flushed when you examine the file. If you are only going to print once every 30 seconds, you may as well open/print/close the file on every iteration of the loop (closing will flush the buffer). Alternatively, you can turn off buffering by setting $|=1; before you start printing.

    Update: ikegami is correct below, another way to turn off buffering besides directly using select and $| (which you can find further down) is:

    use IO::Handle; #(or use IO::File) ... FH->autoflush;

      $|=1 alone will not cut it, since it will only set autoflushing for the currently selected file handle (presumably STDOUT).

Re: Filehandle Print
by davido (Cardinal) on Jan 26, 2005 at 17:36 UTC

    You're just being tripped up by buffering. The filehandle is being written to, but due to buffering nothing is getting flushed right away. If you waited long enough (sleep 30?) eventually the buffer would fill enough to be flushed to the file.

    When you close a filehandle, the buffer is flushed. But this script will never automatically close the filehandle because it never exists from the while loop, and because the only way "out" of the script is to hit ctrl-c, which halts it before the file can be properly flushed/closed.

    I hate to use $|, but you will find that setting $| will probably eliminate the behavior. I would much prefer simply improving the design, rather than using a band-aid.


Re: Filehandle Print
by borisz (Canon) on Jan 26, 2005 at 17:43 UTC
    You could also use
    use IO::Handle; open (REPORT, ">$myfile) || die $!; REPORT->autoflush(1);