Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/241.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在php中为长时间运行的进程创建后台进程_Php_Ajax_Yii_Background Process - Fatal编程技术网

在php中为长时间运行的进程创建后台进程

在php中为长时间运行的进程创建后台进程,php,ajax,yii,background-process,Php,Ajax,Yii,Background Process,好吧,如果这是另一个问题的重复,请原谅我,但在搜索之后,我没有找到一个明确的答案。我基本上想做的是让我的php web应用程序触发一些事件(如电子邮件发送程序或报表生成器),这些事件可能需要几分钟才能完成,并立即将控制权返回到页面。我来自一个.NET世界,在这个世界上,只需一个线程就可以轻松完成 以下是工作流程: 用户单击“生成报告”按钮 ajax调用“../blah/generate report”并立即返回 流程启动并运行,直到完成,而用户可以继续他的业务 用户可以返回报告页面并查看进度:“

好吧,如果这是另一个问题的重复,请原谅我,但在搜索之后,我没有找到一个明确的答案。我基本上想做的是让我的php web应用程序触发一些事件(如电子邮件发送程序或报表生成器),这些事件可能需要几分钟才能完成,并立即将控制权返回到页面。我来自一个.NET世界,在这个世界上,只需一个线程就可以轻松完成

以下是工作流程:

  • 用户单击“生成报告”按钮
  • ajax调用“../blah/generate report”并立即返回
  • 流程启动并运行,直到完成,而用户可以继续他的业务
  • 用户可以返回报告页面并查看进度:“报告完成50%”
  • 实现这一目标的最佳方式是什么?简短的回答很好。我不想要为我写的代码,只是一些指导。我看了shell_exec,但我不确定这是否是最好的方法,或者如果是,如何使用它来处理web应用程序中的功能。(如果有什么不同的话,我正在使用Yii框架)。谢谢

    -Jason

    在PHP中启动一个新的类似线程的东西的最好(也是唯一可行的)方法是使用类似curl的东西创建一个新的PHP请求

    $ch = curl_init();
    
    curl_setopt($ch, CURLOPT_URL, 'http://www.yoursite.com/background-script.php');
    curl_setopt($ch, CURLOPT_FRESH_CONNECT, true);
    curl_setopt($ch, CURLOPT_TIMEOUT_MS, 1);
    
    curl_exec($ch);
    curl_close($ch);
    

    这将运行脚本,并立即返回页面。当然没有回调,所以最好将background-script.php的输出放入数据库,然后每隔一段时间从客户端ping数据库,直到看到结果。

    据我所知,shell\u exec或exec将阻止php脚本的执行,直到进程终止。 一种解决方案是在命令末尾附加一个“&”,脚本/程序将被后台处理

    "/usr/report.sh &"
    
    我曾使用类似的方法从PHP运行外部工具,但通过一个中间脚本来控制PID、实例数。。。
    无法确定它是否在Windows主机下工作。

    我们在这里创建了一个函数,该函数将向浏览器返回答案并继续执行。我们使用它发送电子邮件,而不必让用户等待

    public function redirectAndContinue( $url )
    {
        ignore_user_abort(true);
        header("Location: $url");
        header("Connection: close");
        header("Content-Length: 0");
        flush();
    }
    
    你可以这样使用它

    // do quick basic stuff to validate your report
    
    $this->redirectAndContinue( $url )
    
    // send your email or do other slow stuff
    

    问题是:它不适用于AJAX,它必须是一个常规页面请求(可能是一篇文章)。但是你还是可以制作进度条:在数据库或会话中保存一些内容,然后继续调用一些URL,通过AJAX获取进度。

    我可以推荐Gearman吗?您可以向gearman服务器提交作业并请求状态

    Gearman为使用多台机器或进程提供了分布式应用程序框架。它允许应用程序并行完成任务、负载平衡处理以及在不同语言之间调用函数。该框架可用于各种应用程序。Gearman是多线程的,已知每秒能够执行5万个作业

    这里有一个快速教程:


    这也很容易入门,所有代码都将使用PHP。

    PHP是单线程的。如果您有进程控制扩展,您可以生成额外的PHP进程,但它们不是线程。或者,您可以
    exec('/usr/bin/php name_of_script.php')
    为了更正上述注释,存在向开发人员公开线程功能的pthreads扩展。但是,即使这样,您仍然无法提供HTML和执行后台任务,因为web服务器进程将一直挂起,直到PHP进程完成,并且只有在所有线程完成后才会完成。您需要的是实现作业服务器或任务场。我想起了Gearman,他可能会有所帮助。使用web请求填充不同进程的队列。然后执行另一个HTTP请求来查询作业状态。另一个注释来更正我自己的:)如果您对任何使用线程的机会感兴趣,您可以查看我将链接的存储库,它向您展示如何执行异步请求,如果这解决了您的问题(尽管Drew的回答提供了以较少的麻烦处理该任务的方法).@N.B.我知道pthreads,但它不是一个常用的扩展,并且有某些要求,这可能会导致安装问题。这只是转发原始请求,也就是说,它不会使其异步。例如:如果background-script.php在1分钟内没有重新响应,则在同一会话中发送的任何异步请求都将等到Background脚本将发送其响应。其中的异步是什么?