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

Hello,

I have a question regarding the best way to run a background process in a web application using CGI and Perl. My best attempt currently forks a parent process which creates a dummy output page (that is set to auto-refresh) and then exits. The child is where I am doing all of my work in my script, and while I know it is rather unorthodox to force the parent to exit before the child, I couldn't figure out another way to accomplish backgrounding within my scripts.

The good part of this solution is that it works; the parent creates an auto-refreshing dummy page, and once the child is done, it overwrites the dummy page with the actual output, and when the dummy page auto-refreshes, it loads the real output and stops refreshing.

The bad part about this solution is that I am unable to incrementally print to the dummy page when my subroutines complete (to show progress in the script). My die statements (for when things like open should fail) are completely hidden however.

I am about to start rewriting all of my dies to print their error message to the dummy page as a work-around, but I feel like there must be a better way than the one I have implemented.

And this brings me to you, oh wise monks, seeking any and all advice you may have about this topic. Thank you in advance.

Replies are listed 'Best First'.
Re: CGI Script backgrounding
by ww (Archbishop) on Aug 10, 2011 at 00:20 UTC
Re: CGI Script backgrounding
by locked_user sundialsvc4 (Abbot) on Aug 09, 2011 at 23:44 UTC

    What I would do, first of all, is to recognize that “this is not a new problem.”   It has been solved before.   And the way that it has been solved, in each of its various ways, is to assume the existence of some kind of “batch processing” system, independent of the web-site and of the web-server, to which units of work can be “submitted.”   The web-site then becomes a user interface to that system ... providing the end-user with the ability to submit these units of work, and to inquire as to their completion status, and to retrieve and view the results obtained.

    What I suggest that you do next is ... on-line research.   (Which is a good bit more than just, “Google™ It.”)   Basically, you know right now that you ought not to have to build something new; that you can either buy or obtain an appropriate (and well-tested) solution much less expensively.   But what you do not yet know right now is:   what are the alternatives that might be relevant to my problem, and, of these alternatives, which one should we choose (and why?).   Only good, old-fashioned, “gumshoe research” can tell you that.   (This is not a “blow-off.”)

    Actum Ne Agas:   Do Not Do A Thing Already Done.

      The need for on-line research brought me here, I have scoured the web for many Perl related issues, and this is the first one that I haven't found a clear solution for, probably because there are so many ways to solve this problem.

      Hence why I asked for the wisdom of the Perl Monks, for I know that there are many ways that I can accomplish this task, I am curious as to which one is the best method.

      As to the other two replies, I will look into AJAX a bit more, I stumbled upon it in my searching, yet at first glance I didn't see its utility.

      Thanks for all of the input!

Re: CGI Script backgrounding
by scorpio17 (Canon) on Aug 10, 2011 at 13:33 UTC

    It sounds like you've done the hard part already - good job!

    I suggest the following: if your auto refreshing dummy page is using a meta tag with refresh - get rid of that. Think of your dummy page as a "status" page instead. Add some javascript to the page that will generate status messages via AJAX requests.

    One quick and easy way to do that is to modify your child process (the one doing all the work) so that it writes out status messages to a special log file (needs to be readable by the user your web server runs as). Then create a cgi script that reads in this file dumps it to stout. If you point your web browser to this cgi script, you should see your status messages as plain text. Your 'status' page needs to have an empty DIV with a unique ID. Your ajax code will basically ping your cgi script every few seconds, and stuff whatever output it gets into that DIV element. Start the first ajax request in an onload() event, then make sure the last thing the request handler does is schedule another request in 10 seconds (or however often you think makes sense).

    Note that you can replace all your 'die' statements with something custom, like 'mydie'. These will write the error message to the special status log file before dying - that way the event will show up on your status page.

    You can also store the child processes PID in a file when it first launches, then have the status cgi script check to make sure it's still running. If it disappears from the process list before finishing the job, you'll know something has gone horribly wrong.

    Once you get the basic idea working, you can get fancy: you can use JSON to stringify an entire perl data structure and pass it to your status page via ajax. You could use this to create a kind of "control panel" app, able to manage multiple jobs at once, and implement features like "start job", "stop job", "kill job", etc.

      I am going to look into using AJAX instead, right now I am using a meta tag refresh, and while its wonky, it does work. The whole point of my script is actually to generate a dashboard that outputs the data structure my script generates, so I'm not sure how applicable a control panel is here as there is only ever one command that needs doing-generate the dashboard. Thanks for the info!