Beefy Boxes and Bandwidth Generously Provided by pair Networks
Clear questions and runnable code
get the best and fastest answer
 
PerlMonks  

capture periodic updates from external program

by mabossert (Scribe)
on May 12, 2014 at 21:09 UTC ( [id://1085839]=perlquestion: print w/replies, xml ) Need Help??

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

I have a web application that I use to spawn another program at the user's request. I would like to be able to display a progress bar for the user in the web app...but am a bit confused on how to do that. I have most of the pieces, but can't seem to get it all together. My spawned process (currently) spits out the number of lines processed on a periodic basis to STDOUT (but would prefer this to be more elegant IPC), which I would like to capture while the external program is running and send that back to the user interface via a Websocket connection as a percent complete in a javascript progress bar.

Currently, the external program writes its progress to STDOUT, I have a javascript widget that will accept the progress percentage, I have the web socket connection. What I don't have is a method for executing the external program (I am assuming IPC::Open3, IPC::Run3 or similar) and watching the progress within a loop (while?) until the program terminates (normally or not...I can handle abnormal exits already). During the loop execution, I would like to send the percentage of completion as it is received with a threshold set for the minimum interval between updates (already can handle the update frequency).

Any help or suggestions would be greatly appreciated...I guess that my first attempt at this would be to simply watch STDOUT use a regex to grab the formatted progress updates...but how do I break out of the loop? A not so sophisticated approach is to write "FINISHED" to STDOUT and watch for that...but that seems a bit unsophisticated and prone to errors.

  • Comment on capture periodic updates from external program

Replies are listed 'Best First'.
Re: capture periodic updates from external program
by wjw (Priest) on May 12, 2014 at 21:36 UTC
    As long as your using javascript already, I think I would use something like Progress Bar. Have the background process write to a file instead of STDOUT, and make a little CGI script to serve up the value in the file. javascript takes care of the rest, pinging the CGI until it sees 'complete' or whatever, and puts up a 'congratulations-your done' message. The background process can delete-previous/create-new file on startup(submit) with a unique name for that session which is handed back to the browser on submit at the beginning of the process, thus informing ajax of what it needs to request.

    So I tossed this out here as an idea, but I would guess it has some holes in it. Will be interested to hear what others have done... .

    Just a thought....

    ...the majority is always wrong, and always the last to know about it...
    Insanity: Doing the same thing over and over again and expecting different results...

      Thanks for the feedback! I appreciate the response...but I guess I was not clear with my desired outcome...I am using this: http://demos.telerik.com/kendo-ui/web/progressbar/index.html. Which will definitely handle everything for me as you suggested with ProgressBar (javascript library).

      My main concern is actually with the mechanics of the loop that will supply the updated progress. I need to start execution, then (in a loop) periodically send the progress updates through a web socket message...until the program finishes.

      I know I can kick off execution with open3 or run3, and then watch STDOUT from that program...but how do I break out of the loop? I guess I am not very familiar with how those libraries handle the file handles for STDOUT/ERR.

      I wonder if something like this would work as intended?

      ... run3 "somecommand -i somefile -o someoutputfile", $stdout, $stderr; while(my $line = <$stdout>) { if($line =~ m/Progress: (\d+) lines processed/) { # Assume that $ws is the web socket object I have created and will + allow for the message to be sent... $ws->send($1); } }
Re: capture periodic updates from external program
by scorpio17 (Canon) on May 13, 2014 at 14:04 UTC

      This is getting me all sorts of frustrated. I have reverted to trying a simple test script and external program. The external program does nothing more than print a counter and then sleep for 1 second. I cannot seem to get its output while it is executing...Here is the code for both. Any help would be GREATLY appreciated...

      the "child" program:

      #!/usr/bin/env perl use strict; use warnings; use 5.016; use Carp qw(cluck carp croak); my $c=1; for(1..15) { say 'COUNT: '.$c; $c++; sleep(1); }

      And here is the "parent" program...again, I am open to ANY solution that works. By "works", I mean that I need the output of the child program to be printed as it comes in. For the "real" program, I will need to send a web socket message every time output is received from the child program...the output will be a progress indicator (e.g. 10% complete, 15% complete, etc.).

      First, with Capture::Tiny: (no dice)

      #!/usr/bin/env perl use strict; use warnings; use 5.016; use Carp qw(cluck carp croak); use Data::Dumper; use Capture::Tiny ':all'; local $| = 1; my $cmd = "/tempssd/bossert/bin/testchild.pl &"; my ($stdout, $stderr, @result) = tee { system($cmd); }; while (my $line = <$stdout>) { say 'GOT: '.$line; last if $line =~ m/^FINISHED/; }

      Next, with IPC::Run: (Note, I get the STDOUT AFTER it runs...and it seems that the code ref for the stdout handling never fires.

      #!/usr/bin/env perl use strict; use warnings; use 5.016; use Carp qw(cluck carp croak); use Data::Dumper; use IPC::Run qw(run); local $| = 1; my @cmd = ("/tempssd/bossert/bin/testchild.pl"); run \@cmd, '<', \undef,'>&',\&stdoutH or die "cat: $?"; sub stdoutH { my ($in) = @_; chomp $in; say 'STDOUT: '.$in; }

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1085839]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others exploiting the Monastery: (3)
As of 2024-04-25 23:20 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found