Beefy Boxes and Bandwidth Generously Provided by pair Networks
laziness, impatience, and hubris
 
PerlMonks  

CGI script calling a perl script

by Anonymous Monk
on Apr 24, 2013 at 19:29 UTC ( [id://1030495]=perlquestion: print w/replies, xml ) Need Help??

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

I've got a CGI script which I need to call another perl script (myscript.pl) in the background (non-blocking) and then continue on displaying the HTML headers. I use a $step variable, where $step=0 indicates to launch the Perl script and then $step automatically increments with each automatic page refresh. The page refresh is necessary to display real-time output. My issue is that the call to myscript.pl seems to block and doesn't display any HTML when step=0 is passed as a CGI parameter - although the script is still launched. How can I correct this behavior to make the call non-blocking and display the HTML page? Thanks.
use warnings; use strict; use CGI; use Proc::Background; my $args = new CGI; if(!defined $args->param('step')) { print $args->header; blah blah blah print $args->end_html; exit; } if($args->param('step') == 0) { $step = 1; my $proc1 = Proc::Background->new("perl","./myscript.pl","arg1","arg +2"); } elsif($args->param('step') > 0) { $step = $args->param('step'); $step ++; } print $args->header(-Refresh=>"5;url=http://localhost/cgi-bin/mycgi.pl +?step=$step"); ... print <input type=\"hidden\" name=\"step\" value=\"$step\">"; print $args->end_html; exit;

Replies are listed 'Best First'.
Re: CGI script calling a perl script
by mbethke (Hermit) on Apr 24, 2013 at 19:53 UTC
    I guess the HTML isn't being sent out because it's still sitting in a buffer somewhere and the main CGI process can't exit and flush the buffer as long as there is still a child process active. Proc::Daemon could do what you want but I don't think that's a particularly good architecture to start with. If myscript.pl takes a long time to run (which is the only reason I can imagine for not doing its job on the main task), you could easily be DOSed by calling the page with step=0 repeatedly. Have you thought about using AJAX? You could load the main page and have it call myscript in the background as a CGI of its own, which would then print its results in JSON or something as they are produced, to be consumed by the JavaScript on your page.
      Yes myscript.pl takes a long time to run. I'm not worried about DOS because of various other security mechanisms in place. Unfortunately I don't know AJAX so I'm stuck trying to with CGI and perl. How would Proc::Daemon help in this case? Would it replace Proc::Background?

        Sort of, though the API is different. It helps you completely detach a process from its parent so the parent can exit while the child continues. I guess the child will write some file to the file system than and the parent somehow finds out when it's done?

        If you don't mind forcing users to enable scripting on your page, the whole AJAX stuff isn't all that difficult. Wikipedia on AJAJ has a very small example using jQuery (you could call that function that does $.getJSON in an onLoad handler or so), and the article on XMLHttpRequest has some resources on how to do it without jQuery.

      Is there a way to force flush the buffer?
        I'm not entirely sure about CGI but as it uses STDOUT underneath a
        use IO::Handle; STDOUT->autoflush(1);
        should at least get the HTML out to the web server. It won't solve the problem of the CGI script not exiting and thus not sending an EOF to the browser though, so the browser will keep showing "page loading". Maybe you can close STDOUT before exiting?
Re: CGI script calling a perl script
by igelkott (Priest) on Apr 24, 2013 at 22:10 UTC

    As others suggested, I would use AJAX or some other high-level solution for this. But, if you really want to avoid those options, look into NPH (no-parsed-header) and server-push to maintain page updates. This won't solve everything but it may be enough.

Re: CGI script calling a perl script
by Anonymous Monk on Apr 25, 2013 at 03:11 UTC
    That should work, so you're leaving out some details

Log In?
Username:
Password:

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

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

    No recent polls found