How can I run an external process without waiting for it to finish from a Perl CGI script?
Is it possible to continue displaying a CGI script's HTML without waiting for a child process to complete, yet the child process should stay alive when the CGI script is complete.
Here's what I have,
-- Display HTML page
# html page set up... so header/other stuff
#the -c, -h are params are just params
sys开发者_Go百科tem("perl subprocess.pm -c params -h 1 &");
#actually print the html page setup
...
For some weird reason, it waits for the subprocess to finish before it outputs the html page even though I included the asynchronous system call for linux. It doesn't render the page immediately. Is it possible to print the html page without waiting for the subprocess to finish?
It's possible - please ensure that the autofulush is on (
$|=1;
) as discussed here, or for that matter in "Perl Cookbook" (Chapter 7.12. Flushing Output).You also need to decouple the child process by "daemonizing" it - see Ether's answer to a different question for an example
However, this is not reliable AND is subject to easy breakage due to HTTP timeouts. Therefore the proper solution to display a continuously changing output on a web page is to either:
a. Simpler solution:
Your CGI script prints to a temporary HTML file
once in a while it takes that temp file, closes the HTML and copies the current latest version to some temp location visible from htdocs tree (e.g. that can be referenced by a client via a URL - say
http://your_server/tmp/AYZ122.html
your original CGI's produces an HTTP response redirecting to
http://your_server/tmp/AYZ122.html
after creating the very original version of the temp file and spawning off the child process.The temp HTML file in that location has a META REFRESH which instructs it to refresh itself every N seconds (say 10) and appropriate message/CSS for the user warning that the loading is in progress and please wait.
b. Harder solution:
Somewhat similar in that the main CGI script creates a "please wait" HTML page sent to the user, and launches a child process which writes a temp file.
The temp file created by the child process, however, is not necessarily a whole HTML page, but some data file.
The main HTML page created by original CGI script contains a loop which issues AJAX calls that retrieve the latest data (the retrieval process will read the temp file written by child process) and updates the HTML page according to latest data.
There is another solution: use SSI (Server side includes). Your CGI-program :
- 1) creates a temporary web-page "Please wait" that contains directive #include virtual log-file;
- 2) initializes log-file, f.e. writes there the first message;
- 3) silently launches the main subprocess;
- 4) silently launches the checker subprocess;
- 5) generates a web page that has META-tag
REFRESH
with redirection to the temporary web-page. The temporary web page has meta-tag REFRESH without redirection.
The checker sub-process every N seconds checks the status of the main subprocess. When the main process finishes, either normally or abnormally, the checker process creates the final web page without REFRESH meta-tag with the same name as the temporary web-page.
The effects is that the log-file is shown to a user and continuously updated every N seconds before the main subprocess finishes.
Watching long processes through CGI
精彩评论