强制代码在页面关闭后继续运行


force the code to keep running after page closes

我有一个While循环(函数),它可以工作几分钟,有时可能需要10分钟,有时则需要30分钟。

我不想让用户在打开网页窗口的情况下等待30分钟,我想让用户关闭窗口,让循环自己继续。

我希望用户打开网页,点击按钮启动功能,然后关闭页面,让功能自行运行。

这样的事情有可能发生吗?

您可以查看fastcgi_finish_request()。它允许脚本继续运行,但"挂断"与浏览器的连接。当然,应该小心使用它,否则可能会有许多进程在半后台运行的风险。

当然,这只适用于php-fpm。否则,您将看到像gearman这样的东西,基本上是任何类型的任务调度器。

如果脚本超时(php.ini中的max_execution_time设置)对您来说没有问题,您可以使用ignore_user_abort(true)

但对于此类任务,通常更好的解决方案是在后台生成它们。Gearman扩展可能对您或exec的不同变体感兴趣。

用户操作不会导致脚本停止。

脚本将继续,直到它完成或达到超时(在大多数服务器上是15或30秒),所以如果你有自己的服务器或没有超时的私人服务器,你的脚本将运行30分钟,用户对它没有影响。

您应该注意的是,如果用户在时间范围内刷新页面或再次访问,则不允许脚本再次运行。

function execInBackground($cmd) { 
    if (substr(php_uname(), 0, 7) == "Windows"){ 
        pclose(popen("start /B ". $cmd, "r"));  
    } 
    else { 
        exec($cmd . " > /dev/null &");   
    } 
} 

或者db+cron解决方案。

我过去也做过类似的事情。

class Task {
  function add($command)
  function execute();
}
class TaskManager {
  function run(){
    $task->execute();
  }
}

任务以脚本或shell命令的形式添加到队列(DB、平面文件、雕刻在石头上的东西,无论你喜欢什么)中。然后TaskManager作为服务运行(http://php.net/manual/en/function.pcntl-fork.php)并不断地从队列中取出第一个项目并执行它

通过这种方式,您可以在后台为长时间运行的任务提供服务,并且不会有很多流氓进程启动。

我认为您需要重新思考为什么在前端运行如此长的流程。为什么不把一个工作队列放在适当的位置,让后台守护程序或服务进程尽可能快地处理呢。

如果太多人都有开放的进程,php无法处理任何新线程,那么当前会发生什么?

当出现错误或需要重试处理时会发生什么?