2008-11-05 137 views
41

我试图做一个PHP脚本,我已经完成脚本,但它需要10分钟才能完成它旨在执行的过程。这不是一个问题,但我认为我必须保持页面加载所有这是令人讨厌的。我是否可以拥有它,以便我开始此过程,然后在10分钟后回来并查看它生成的日志文件?PHP后台进程

回答

50

那么,你可以使用“ignore_user_abort(真)”

因此脚本将继续工作(保持对脚本持续的眼睛,也许加上“set_time_limit(0)”)

但警告在这里:你将无法停止脚本这两条线:

ignore_user_abort(true); 
set_time_limit(0); 

除了可以直接访问服务器,并有杀死进程! (去过那里,做一个死循环,在自称一遍又一遍,取得了服务器来嘎然停止,在得到了喊...)

+0

这是辉煌的。这也适用于WordPress的Ajax调用'wp_ajax_nopriv_your_trigger'。在你的钩子中使用上面的两个方法,并调用(可能使用调度器)http://yourdomain.com/wp-admin/admin-ajax.php?action=your_trigger – 2010-12-17 00:49:16

+0

工作就像一个魅力!我正在将文件上传到我的服务器,然后使用此方法的脚本将其上传到S3,以便我可以轻松地向用户显示上传进度。我很爽快,其他请求和什么不在我的网站。你看,这个文件在S3中,我的日志显示了进程。 :D – 2013-03-03 03:03:37

+0

@azure_ardee WordPress已经有了一个模拟cron系统来处理这样的事情。请参阅http://codex.wordpress.org/Function_Reference/wp_cron – 2013-11-11 20:50:21

3

你可以使用ignore_user_abort() - 这样的脚本将继续,即使你关闭你的浏览器中运行或转到其他页面。

8

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

出于某种原因;我遇到了问题,要么挂起其他请求,要么在约60秒后超时(在约20分钟后,apache和php都设置为超时);它也证明,无论如何5分钟后(默认情况下)firefox超时,所以在那之后你不知道通过浏览器发生了什么,而不改变Firefox的设置。

我结束了在使用过程中打开和处理close方法在命令行模式下打开了一个PHP像这样:

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

这(使用开始)打开PHP程序,然后杀死开始进程离开PHP运行,无论它需要多长时间 - 再次,你需要杀死进程手动关闭它。它不需要你设置任何超时,你可以让当前页面调用它并继续输出更多的细节。

唯一的问题是,如果你需要发送脚本的任何数据,你要么通过另一个来源或通过“命令行”作为参数传递;这并不安全。

很好地为我们所需要的工作,并确保脚本始终启动,并允许运行没有任何中断。

26

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

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

这里的优点是你不会锁定一个Apache线程10分钟。

4

还有另一种选择,你可以使用,运行脚本CLI ...它会在后台运行,你甚至可以运行它作为cronjob如果你想。

e.g

> #!/usr/bin/php -q 

<?php 

//process logs 

?> 

这可以设置为一个cronjob并且将没有时间限制执行....这样的例子是用于基于Unix的操作系统虽然。

FYI 我有一个php脚本运行一个无限循环,它执行一些处理,并且已经运行了过去3个月不停。

2

想想Gearman

Gearman的是工作外包出去,以 多台机器或流程的通用应用程序框架。它允许应用程序并行完成 任务,负载平衡处理以及在语言之间调用功能 。该框架可用于从高可用性网站到传输数据库复制事件的各种 应用程序。

此扩展提供了用于编写Gearman客户端和 工人的类。 - 源PHP手册

Gearman

1

ZUK的官方网站。

我敢肯定,这将工作:

<?php 

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

?> 

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

,你也可以在你的服务器停止命令在你的PHP使用此代码(如 “bastiandoeen” 之称)

ignore_user_abort(true); 
set_time_limit(0); 

​​
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

如果你想卷曲在不到一秒钟的超时时间,你可以使用 CURLOPT_TIMEOUT_MS,虽然“Unix-like 系统”中存在bug /“功能”,导致libcurl立即超时,如果该值为< 1000 ms,出现错误“cURL Error(28):Timeout reached reached”。该 解释这种行为是:

[...]

的解决方案是使用CURLOPT_NOSIGNAL

利弊

  • 无需切换输入法禁用信号(兼容窗口& linux)
  • 无需设置NT连接通过页眉和缓冲(独立于浏览器和PHP版本)

利弊处理

  • 需要curl扩展

资源