简体   繁体   中英

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.

  • It has to be invoked by an HTTP request . There should be no HTTP request waiting for some minutes so the script has to run still AFTER the visitor got his HTTP response.
  • It has to run periodically (every night) . It also should run every night per default (like a cron job). Notice: since the software is going to be distributed to clients there is no way for us to add a cronjob manually (we have no access to our clients servers). Everything should be accomplished within PHP code.

(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.

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM