我有一个运行几分钟的 While 循环(函数),有时可能需要 10 分钟,有时需要 30 分钟。
我不想让用户等待网页窗口打开 30 分钟,我想让用户关闭窗口并让循环自行继续。
我希望用户打开网页单击一个按钮以启动该功能,然后关闭该页面并让该功能自行工作。
有没有可能发生这样的事情?
我有一个运行几分钟的 While 循环(函数),有时可能需要 10 分钟,有时需要 30 分钟。
我不想让用户等待网页窗口打开 30 分钟,我想让用户关闭窗口并让循环自行继续。
我希望用户打开网页单击一个按钮以启动该功能,然后关闭该页面并让该功能自行工作。
有没有可能发生这样的事情?
你可以去看看fastcgi_finish_request()
。它允许您的脚本继续运行,但“挂断”与浏览器的连接。当然应该小心使用它,否则您可能会冒许多进程在半后台运行的风险。
当然,这仅适用于 php-fpm。否则你会看到类似的东西gearman
,基本上是任何类型的任务调度程序。
如果脚本超时(max_execution_time
设置 in php.ini
)对您来说没有问题,您可以使用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 命令添加到队列(数据库、平面文件、刻在石头上的任何东西)中。然后 TaskManager 作为服务运行(在http://php.net/manual/en/function.pcntl-fork.php有一些很好的评论)并不断从队列中取出第一项并执行它。
通过这种方式,您可以在后台为长时间运行的任务提供服务,并且您不会启动很多恶意进程。
我认为您需要重新考虑为什么要像这样在前端运行如此长的进程。为什么不放置一个工作队列并让后台守护程序或服务进程尽可能快地运行。
如果太多人有打开的进程并且 php 无法启动任何新线程,目前会发生什么?
发生错误或需要重试处理时会发生什么?