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

Hi I am new to pearl and have been asked to create a perl script that executes a stats command on a program on our server.

The program on our server generates lines of stats every minute as follows(it runs indefinetly until you hit ctrl +c):

HH:MM:SS - 1,2,3

HH:MM:SS - 1,2,3

I want to runs this stats program so it always runs in the background and capture the output to a fifo. I then want read the last 30 lines(to give me the last 30 mins) in the fifo and write this to a actual file e.g. <timestamp>.csv (this file is then collected by a graphing program)

Can anyone suggesest the best way to do this. I have been googling and it seems like the best way is using forks and fifo's (which is all new to me)

  • Comment on Help with fork, read and write from a pipe

Replies are listed 'Best First'.
Re: Help with fork, read and write from a pipe
by zentara (Cardinal) on Jan 22, 2014 at 16:18 UTC
    Assuming you want real pipes, here is a little example script:
    #!/usr/bin/perl use warnings; use strict; use IO::Handle; $|++; pipe( PARENT_READER, CHILD_WRITER ); pipe( CHILD_READER, PARENT_WRITER ); PARENT_WRITER->autoflush(1); CHILD_WRITER->autoflush(1); my $pid; if ( $pid = fork() ) { close(CHILD_READER); close(CHILD_WRITER); my $buffer; print PARENT_WRITER 1; while (1) { sysread( PARENT_READER, $buffer, 100 ); print "parent revd: $buffer, and reply with ", $buffer + 1, "\ +n"; sleep(1); print PARENT_WRITER $buffer + 1; } } else { close(PARENT_READER); close(PARENT_WRITER); my $buffer; while (1) { sysread( CHILD_READER, $buffer, 1000 ); print "child revd: $buffer, and reply with ", $buffer + 1, "\n +"; sleep(1); print CHILD_WRITER $buffer + 1; } }

    but this simpler example may be more useful to you.

    #!/usr/bin/perl use strict; use warnings; my $pid = open(CHILD, "-|"); if ($pid) { # parent print "parent got:\n"; print while(<CHILD>); close CHILD; # this waits on child } elsif ($pid == 0) { # child print "kid here!\n"; exec '/bin/date' or die "Can't exec date $!\n"; } else { die "fork error: $!\n"; }

    I'm not really a human, but I play one on earth.
    Old Perl Programmer Haiku ................... flash japh
Re: Help with fork, read and write from a pipe
by McA (Priest) on Jan 22, 2014 at 16:31 UTC

    A little starting point:

    #!/usr/bin/perl use strict; use warnings; print "Starting external program. Waiting for input.\n"; open my $fh, "-|", "while true; do date; sleep 1; done"; my @lines; while(defined(my $line = <$fh>)) { chomp $line; push @lines, $line; if(@lines >= 20) { my $howmuch = @lines; print "Read '$howmuch' lines from external program.\n"; print "Stats are...calc calc calc.\n"; print "The following lines where read:\n"; print map { "$_\n"; } splice @lines; print "Going to sleep.\n"; sleep 20; } }

    Looking at the docs of the used commands should push you forward. Search here helps also (reading from external program, capturing from external program).

    Best regards
    McA

      Hi, Thanks this has helped. I am now able to generate my files once it has the 20 lines

        I'm happy to hear that. Thanks for the feedback.

Re: Help with fork, read and write from a pipe
by Anonymous Monk on Jan 22, 2014 at 20:00 UTC
    And maybe if you're using a Unix/Linux environment you can do the first part of this task with the shell ... simply piping the stats program's input into the STDIN of another script that say does a sleep 30*60 followed by a tail -n 30 ... which output is then piped (by the main script) into the actual CSV-conversion (Perl?) routine. This pushes a lot of the complexity of the task out of the domain of Perl and into an environment which is really set up to do this sort of thing. A "pure-Perl solution" is not the only way to do it. Worth considering.
Re: Help with fork, read and write from a pipe
by Anonymous Monk on Jan 23, 2014 at 05:49 UTC
    I may have misunderstood the qn, but it seems like http://search.cpan.org/~mgrabnar/File-Tail-0.99.3/Tail.pm is sufficient, then just dump each N (eg 30) lines to a new o/p file