PHP后台进程

时间:2008-11-05 13:00:51

标签: php background-process

我正在尝试创建一个PHP脚本,我已经完成了脚本,但是它需要10分钟才能完成它的设计过程。这不是问题,但我认为我必须始终保持页面加载这很烦人。我可以拥有它以便我启动该过程然后在10分钟后返回并查看它生成的日志文件吗?

11 个答案:

答案 0 :(得分:50)

好吧,你可以使用“ignore_user_abort(true)”

因此脚本将继续工作(密切关注脚本持续时间,也许添加“set_time_limit(0)”)

但是这里有一个警告:你将无法使用这两行停止脚本:

ignore_user_abort(true); 
set_time_limit(0);

除了你可以直接访问服务器并杀死那里的进程! (在那里,做了一个无休止的循环,一遍又一遍地呼唤自己,让服务器突然停下来,大声喊叫......)

答案 1 :(得分:26)

听起来你应该有一个队列和一个外部脚本来处理队列。

例如,您的PHP脚本应该将一个条目放入数据库表并立即返回。然后,每分钟运行一次的cron检查队列并为每个作业分叉一个进程。

这里的优点是你不会将apache线程锁定10分钟。

答案 2 :(得分:8)

我在windows下遇到了很多关于这种过程的问题;我的情况有点不同,因为我不关心“脚本”的响应 - 我希望脚本启动并允许其他页面请求在忙着工作时通过。

出于某种原因;我有问题要么挂掉其他请求,要么在大约60秒后超时(apache和php都会在大约20分钟后超时);事实证明firefox在5分钟后(默认情况下)会超时,所以在那之后你无法在不改变firefox设置的情况下通过浏览器知道发生了什么。

我最终使用进程打开并处理close方法在cli模式下打开php,如下所示:

pclose(popen("start php myscript.php", "r"));

这将(使用start)打开php进程然后终止启动进程让php运行不管它需要多长时间 - 再次你需要杀死进程来手动关闭它。它不需要您设置任何超时,您可以让当前调用它的页面继续并输出更多详细信息。

唯一的问题是,如果您需要向脚本发送任何数据,您可以通过其他来源执行此操作,也可以将其作为参数传递给“命令行”;这不太安全。

很好地完成了我们所需要的工作,并确保脚本始终启动并允许其运行而不会中断。

答案 3 :(得分:6)

这也可能有所帮助:Asynchronous shell exec in PHP

答案 4 :(得分:5)

我认为shell_exec命令就是你要找的。

但是,它在安全模式下禁用。

关于它的PHP手册文章在这里:http://php.net/shell_exec

这里有一篇关于它的文章:http://nsaunders.wordpress.com/2007/01/12/running-a-background-process-in-php/

答案 5 :(得分:4)

您可以使用另一个选项,运行脚本CLI ...它将在后台运行,您甚至可以根据需要将其作为cronjob运行。

例如

> #!/usr/bin/php -q

<?php

//process logs

?>

这可以设置为cronjob并且将在没有时间限制的情况下执行....这个示例适用于基于unix的操作系统。

FYI 我有一个运行了无限循环的PHP脚本,它进行了一些处理,并且在过去3个月内一直在运行。

答案 6 :(得分:3)

您可以使用ignore_user_abort() - 即使您关闭浏览器或转到其他页面,脚本也会继续运行。

答案 7 :(得分:2)

考虑Gearman

  

Gearman是一个通用的应用程序框架,用于耕种工作   多台机器或流程。它允许应用程序完成   并行任务,负载均衡处理和调用函数   语言之间。该框架可以用于各种各样的   应用程序,从高可用性网站到运输   数据库复制事件。

     

此扩展提供了编写Gearman客户端的类   工作人员。    - 源码php手册

Gearman

的官方网站

答案 8 :(得分:2)

除了bastiandoeen的答案,您可以将ignore_user_abort(true); cUrl请求合并。

伪造请求堕胎设置低CURLOPT_TIMEOUT_MS并在连接关闭后继续处理:

function async_curl($background_process=''){

    //-------------get curl contents----------------

    $ch = curl_init($background_process);
    curl_setopt_array($ch, array(
        CURLOPT_HEADER => 0,
        CURLOPT_RETURNTRANSFER =>true,
        CURLOPT_NOSIGNAL => 1, //to timeout immediately if the value is < 1000 ms
        CURLOPT_TIMEOUT_MS => 50, //The maximum number of mseconds to allow cURL functions to execute
        CURLOPT_VERBOSE => 1,
        CURLOPT_HEADER => 1
    ));
    $out = curl_exec($ch);

    //-------------parse curl contents----------------

    //$header_size = curl_getinfo($ch, CURLINFO_HEADER_SIZE);
    //$header = substr($out, 0, $header_size);
    //$body = substr($out, $header_size);

    curl_close($ch);

    return true;
}

async_curl('http://example.com/background_process_1.php');

<强> NB

  

如果您希望cURL在不到一秒的时间内超时,您可以使用   CURLOPT_TIMEOUT_MS,虽然“类Unix”上有一个错误/“功能”   系统“导致libcurl立即超时,如果值是&lt;   1000 ms,错误“cURL错误(28):达到超时”。该   这种行为的解释是:

     

[...]

     

解决方案是使用CURLOPT_NOSIGNAL

禁用信号

<强>优点

  • 无需切换方法(兼容的Windows和Linux)
  • 无需通过标头和缓冲区实现连接处理(独立于浏览器和PHP版本)

<强>缺点

  • 需要卷曲延伸

<强>资源

答案 9 :(得分:1)

ZUK。

我很确定这会奏效:

<?php 

pclose(popen('php /path/to/file/server.php &'));
echo "Server started. [OK]"; 

?>

'&amp;'很重要它告诉shell不要等待进程退出。

此外,您可以在您的PHP中使用此代码(如“bastiandoeen”所述)

ignore_user_abort(true); 
set_time_limit(0);
服务器停止命令中的

<?php

$output;
exec('ps aux | grep -ie /path/to/file/server.php | awk \'{print $2}\' | xargs kill -9 ', $output);
    echo "Server stopped. [OK]";

?>

答案 10 :(得分:-1)

只需在任何输出之前调用StartBuffer(),并在要客户端关闭连接时调用EndBuffer()。调用EndBuffer()之后的代码将在没有客户端连接的服务器上执行。


    private function StartBuffer(){
        @ini_set('zlib.output_compression',0);
        @ini_set('implicit_flush',1);
        @ob_end_clean();
        @set_time_limit(0);
        @ob_implicit_flush(1);
        @ob_start();
    }

    private function EndBuffer(){
        $size = ob_get_length();
        header("Content-Length: $size");
        header('Connection: close');
        ob_flush();ob_implicit_flush(1);
    }