Michael Käfer
Michael Käfer

Reputation: 1786

Best practise to execute long running PHP scripts

We need to distribute software which should contain a PHP script which will run for some minutes. Therefore I am searching a best practise way to do this in 2017.


(Please note that I read existing blog posts and Stackoverflow questions myself but I could not find a satisfying answer)

Maybe anyone knows how frameworks like Symfony and Laravel or webshops like Magento accomplish such tasks? Still I want to know how to do it by myself in plain PHP without using frameworks or libraries.

Upvotes: 2

Views: 5715

Answers (3)

Michael Käfer
Michael Käfer

Reputation: 1786

Finally I think there are two ways to start a long running process in PHP via an HTTP request (without letting the user wait for a long time):

  • Using FPM and send the response to the user with fastcgi_finish_request(). After the response is sent you can do whatever you want, for example long running tasks. (Here you don't have to start a new process, just continue with PHP).

    fastcgi_finish_request();
    longrunningtask();
    
  • Create a new process using one of the following functions. Redirect STDOUT and STDERR to null and put it to the background (you have to do both). To still get output of the new process the new process can write to some log file.

    exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    shell_exec('php longrunningtask.php >/dev/null 2>/dev/null &');
    system('php longrunningtask.php >/dev/null 2>/dev/null &');
    passthru('php longrunningtask.php >/dev/null 2>/dev/null &');
    

    Or use proc_open() like symfony/process does.


Notes:

  • symfony/process: on the docs you can read that you can use FPM and fastcgi_finish_request() for long running tasks.
  • Security: I can see no built in security risk, you just have to do things right then everything is fine (you could use password protection, validate possible inputs to your commands, etc.).
  • For the cron-job-part of the question there is no answer. I don't think it's possible.

Upvotes: 2

Vladimir Samsonov
Vladimir Samsonov

Reputation: 1329

Magento only runs it cronjobs, if you setup a regular cronjob for Magento. It has a cron.sh, that runs every minute an executes jobs in Magento's queue.

Any Solution to execute long-running tasks via http involves web-server configuration.

Upvotes: 1

Thomas Dutrion
Thomas Dutrion

Reputation: 1893

Many solutions exist:

  • using exec (rather insecure), that triggers a background job (recommended in comments, I would probably prefer symfony process, but insecure nevertheless).
  • using a cron to trigger a symfony process every so often, not over http so way more secure.
  • using php-fpm, you can send a response without stopping the process using fastcgi_finish_request
  • using a queue system (SQS, RabbitMQ, Kafka and so on).
  • using a cron manager in PHP
  • using a daemon and something like supervisord to make sure it runs continuously.

The best solutions are definitely queues and cron, then PHP-FPM, rest of it is just rubbish.

There is absolutely no way for you to run on someone's server without doing something that won't work at some point.

Sidenote: you said you did not want libraries in order to know how to do it yourself, I added links to libraries as reading them may give you a deeper knowledge of the technology, these libraries are really high quality.

Upvotes: 6

Related Questions