Piping ping into perl-prog

B

bernd wegener

Hello netties,

I coded the following in perl:

open(LOGFILE,">&STDOUT") ;

if ( $ARGV[0] ) {

close(LOGFILE) ;
open(LOGFILE,">> $ARGV[0]") or die "Cannot open file $ARGV[0]\n" ;
select(LOGFILE) ; # If commented out, nothing
$| = 1 ; # is printed to $ARGV[0] later on

}

while ( <STDIN> ) {

( $sec, $min, $hour, $day, $month, $year ) = localtime() ;
$month += 1 ;
$year += 1900 ;

printf LOGFILE ("%02d.%02d.%04d %02d:%02d:%02d: %s", $day, $month,
$year,
$hour, $min, $sec, $_) ;

}

The program is intended to receive input line by line from STDIN
(continuously, e.g. from UNIX-commands like ping or tail -f) and to
print the input line prepended with a timestamp either to STDOUT or to
a file if a file name is given on the command line.

If I pipe an "ordinary" file to this program:

$ cat test_inp.txt | tstamp.pl

I get all lines of the file printed to the terminal or to a file:

$ cat test_inp.txt | tstamp.pl test_out.txt

each line prepended with the time stamp.

If I try the same with the select-function and the setting of
unbuffered output commented out, i.e.,

close(LOGFILE) ;
open(LOGFILE,">> $ARGV[0]") or die "Cannot open file $ARGV[0]\n" ;
# select(LOGFILE) ; # If commented out, nothing
# $| = 1 ; # is printed to $ARGV[0] later on

and redirect from a continuously writing program:

ping <host> | tstamp.pl

I get proper output on the terminal, but a file as the output target
remains empty. If instead unbuffered output is used ($| = 1), then
output to the file works fine as well.

Does somebody know the reason for this ?

Any help is appreciated.

Cheers


Bernd
 
J

Joe Smith

bernd said:
ping <host> | tstamp.pl

I get proper output on the terminal, but a file as the output target
remains empty. If instead unbuffered output is used ($| = 1), then
output to the file works fine as well.

You mean "the output target file remains empty until perl's internal
buffers fill up and perl writes several K bytes all at once".
Try letting the program run for 24 hours and see what happens.
Does somebody know the reason for this ?

That behavior is exactly what $| was created to control.
The stdio routines operate differently based on whether the C library
routine isatty() returns 1 or 0, and perl does so as well.
Output to non tty file handles gets buffered.
-Joe
 
B

bernd wegener

Joe Smith said:
You mean "the output target file remains empty until perl's internal
buffers fill up and perl writes several K bytes all at once".
Try letting the program run for 24 hours and see what happens.


That behavior is exactly what $| was created to control.
The stdio routines operate differently based on whether the C library
routine isatty() returns 1 or 0, and perl does so as well.
Output to non tty file handles gets buffered.
-Joe

Hi Joe,

thanks, that was a short but instructive lesson in I/O. If one knows
it is quite straightforward to understand, but since I was not patient
enough I did not see "the end", i.e. that eventually the data is
written to the file. I was not aware of the fact that the
stdio-library differentiates between terminals and disk files in that
way.

I made a little "experiment" on my UNIX-Box, which turned out that the
first chunk of data written to the file was 8K of size (after a few
minutes, so it was not necessary to wait 24 h staring at the terminal
:->>).

I took the Perl Cookbook, reading a little bit more about buffered /
non-buffered output ... ;-)

Thanks and Bye.

Bernd
 
J

Jim Gibson

bernd said:
Hello netties,

I coded the following in perl:

open(LOGFILE,">&STDOUT") ;

if ( $ARGV[0] ) {

close(LOGFILE) ;
open(LOGFILE,">> $ARGV[0]") or die "Cannot open file $ARGV[0]\n" ;
select(LOGFILE) ; # If commented out, nothing
$| = 1 ; # is printed to $ARGV[0] later on

}

while ( <STDIN> ) {

( $sec, $min, $hour, $day, $month, $year ) = localtime() ;
$month += 1 ;
$year += 1900 ;

printf LOGFILE ("%02d.%02d.%04d %02d:%02d:%02d: %s", $day, $month,
$year,
$hour, $min, $sec, $_) ;

}

The program is intended to receive input line by line from STDIN
(continuously, e.g. from UNIX-commands like ping or tail -f) and to
print the input line prepended with a timestamp either to STDOUT or to
a file if a file name is given on the command line.

If I pipe an "ordinary" file to this program:

$ cat test_inp.txt | tstamp.pl

I get all lines of the file printed to the terminal or to a file:

$ cat test_inp.txt | tstamp.pl test_out.txt

each line prepended with the time stamp.

If I try the same with the select-function and the setting of
unbuffered output commented out, i.e.,

close(LOGFILE) ;
open(LOGFILE,">> $ARGV[0]") or die "Cannot open file $ARGV[0]\n" ;
# select(LOGFILE) ; # If commented out, nothing
# $| = 1 ; # is printed to $ARGV[0] later on

and redirect from a continuously writing program:

ping <host> | tstamp.pl

I get proper output on the terminal, but a file as the output target
remains empty. If instead unbuffered output is used ($| = 1), then
output to the file works fine as well.

What do you mean by "proper output on the terminal". When I run this
command, I get no output on the terminal, but I do get output to the
file. Of course, I have to wait awhile because the output is buffered
and it takes a minute for the ping command to fill up a buffer-full.
You shouldn't be getting output from the ping command on your terminal
because you are only writing it to a file.
Does somebody know the reason for this ?

I cannot reproduce your results.

FYI: this newsgroup is defunct; try comp.lang.perl.misc in the future.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,262
Messages
2,571,048
Members
48,769
Latest member
Clifft

Latest Threads

Top