我有一个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无法处理任何新线程,那么当前会发生什么?
当出现错误或需要重试处理时会发生什么?