I have an HTML form that submits to a PHP page which initiates a script. The script can take anywhere from 3 seconds to 30 seconds to run - the user doesn't need to be around for this script to complete.
Is it possible to initiate a PHP script, immediately print "Thanks" to the user (or whatever) and let them go on their merry way while your script continues to work?
In my particular case, I am sending form-data to a php script that then posts the data to numerous other locations. Waiting for all of the posts to succeed is not in my interest at the moment. I would just like to let the script run, allow the user to go and do whatever else they like, and that's it.
-
Place your long term work in another php script, for example
background.php:
sleep(10); file_put_contents('foo.txt',mktime());foreground.php
$unused_but_required = array(); proc_close(proc_open ("php background.php &", array(), $unused_but_required)); echo("Done);You'll see "Done" immediately, and the file will get written 10 seconds later.
I think proc_close works because we've giving proc_open no pipes, and no file descriptors.
Jonathan Sampson : Could you be a bit more descriptive in your answer?thomasrutter : Could you explain how it works? Looks like it tries to close the process immediately after it opens. According to proc_close documentation, it will wait for the process to terminate - isn't this what we wanted to avoid?Gabriel Sosa : I use this method to do threading and works really wellDaniel Von Fange : Updated with more sample code.Jonathan Sampson : Daniel, how would you pass the $_POST/$_GET values to the background.php script?Daniel Von Fange : You could write them into a database table, and pass it the id as a argument, or you could serialize() the $_REQUEST and pass it as an argument (make sure to have it escaped)Bob Somers : I'd say you should avoid passing parameters to the script over the command line at all costs. All it takes is one poorly sanitized input and you've seriously compromised your system. -
You could try the
flushand related output buffer functions to immediately send the whatever is in the buffer to the browser: -
In the script you can set:
<?php ignore_user_abort(true);That way the script will not terminate when the user leaves the page. However be very carefull when combining this whith
set_time_limit(0);Since then the script could execute forever.
-
You can use
set_time_limitandignore_user_abort, but generally speaking, I would recommend that you put the job in a queue and use an asynchronous script to process it. It's a much simpler and durable design. -
Theres an API wrapper around pcntl_fork() called php_fork.
But also, this question was on the Daily WTF... don't pound a nail with a glass bottle.
-
I ended up with the following.
<?php // Ignore User-Requests to Abort ignore_user_abort(true); // Maximum Execution Time In Seconds set_time_limit(30); header("Content-Length: 0"); flush(); /* Loooooooong process */ ?>
0 comments:
Post a Comment