creating background processes in php for long runn

2020-04-11 04:45发布

问题:

Ok so forgive me if this is a repeat of another question, but after searching I have not found a clear answer. What I basically want to do is have my php web application fire off some event (like an emailer or report generator) that may take a few minutes to complete and immediately return control to the page. I come from a .NET world where this can easily be accomplished with a thread.

So here's the workflow:

  1. User clicks 'generate Report' button
  2. ajax call made to '../blah/generate-report' and returns immediately
  3. process is started and runs until completion while the user can then go about his business
  4. User can return to report page and see progress: "Report 50% complete"

What's the best way to accomplish this? Brief answers are fine. I don't want code written for me, just some guidance. I looked at shell_exec but I'm not sure exactly if that is the best way or if it is, how to use it to process functions within a web app. (I'm using the Yii framework if that makes any difference). Thanks.

-Jason

回答1:

The best (and only AFAIK) way to start a new thread thread like thing in PHP is to create a new PHP request using something like curl.

$ch = curl_init();

curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php');
curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);

curl_exec($ch);
curl_close($ch);

This will run the script, and immediately return the page. Of course there's no callback, so your best bet is to put the output of background-script.php into a database, and then ping the database every so often from the client until you see the results.



回答2:

We've created a function here that returns an answer to the browser and keeps executing. We use it to send email without making the user wait for it.

public function redirectAndContinue( $url )
{
    ignore_user_abort(true);
    header("Location: $url");
    header("Connection: close");
    header("Content-Length: 0");
    flush();
}

You may use it like this

// do quick basic stuff to validate your report

$this->redirectAndContinue( $url )

// send your email or do other slow stuff

The problem is: it doesn't work with AJAX, it must be a regular page request (possibly with a POST). But you can make the progress bar anyway: save something in your database or session and then keep calling some URL to get the progress via AJAX.



回答3:

As far as I remember, shell_exec or exec will block the execution of your PHP script until the process will terminate. A solution is to append a "&" at the end of your command, your script/program will be backgrounded.

"/usr/report.sh &"

I have used something like that to run external tool from PHP, but passing by an intermediary script to control PID, number of instances... Can't say if it is working under Windows host.



回答4:

May I suggest Gearman? You can submit jobs to a gearman server and request the status.

Gearman provides a distributed application framework for work with multiple machines or processes. It allows applications to complete tasks in parallel, to load balance processing and to call functions between languages. The framework can be used in a variety of applications. Gearman is multi-threaded and is known to be able to carry out 50 thousand jobs per-second.

A quick tutorial is here: http://www.sitepoint.com/introduction-gearman-multi-tasking-php/

Its also quite easy to get started, and all your code will be in PHP.