2

我想做一个长期的工作,我不能修改最大执行时间,所以我采取了一个解决方案:当脚本要关闭时,脚本会向自己发送一个http请求,所以脚本可以继续运行。 这是我的测试脚本 t.php

<?php 
define('DS', DIRECTORY_SEPARATOR);
define('ROOT', dirname(__FILE__));

function post_request_async($url, ARRAY $data) {
    // Convert the data array into URL Parameters like a=b&foo=bar etc.
    $data = http_build_query($data);
    // parse the given URL
    $url = parse_url($url);
    $host = $url['host'];
    $path = $url['path'];
    $port = isset($url['port']) ? $url['port'] : "80";
    $fp = fsockopen($host, $port, $errno, $errstr, 5);
    if ($fp){
        $req = "";
        $req.="POST $path HTTP/1.0\r\n";
        $req.="Host: $host\r\n";
        $req.="Content-type: application/x-www-form-urlencoded\r\n";
        $req.="Content-length: ". strlen($data) ."\r\n";
        $req.="Connection: close\r\n\r\n";
        $req.= $data;
        fputs($fp, $req);
        fclose($fp);
    }
}

set_time_limit(10);
register_shutdown_function("shutdown_func");

file_put_contents(ROOT.DS."zz.txt", date("Y-m-d H:i:s")." start -->".PHP_EOL, FILE_APPEND);

function shutdown_func(){
    file_put_contents(ROOT.DS."zz.txt", date("Y-m-d H:i:s")." shutdown_func -->".PHP_EOL, FILE_APPEND);
    post_request_async("http://127.0.0.1/t.php", array());
    exit();
}

for(;;) {
    sleep(2);
}
?>

但是结果很奇怪:zz.txt

2012-05-16 10:11:42 start -->
2012-05-16 10:11:54 shutdown_func -->
2012-05-16 10:11:54 start -->
2012-05-16 10:12:04 shutdown_func -->
2012-05-16 10:12:04 start -->
2012-05-16 10:12:14 shutdown_func -->
2012-05-16 10:12:14 start -->
2012-05-16 10:12:26 shutdown_func -->
2012-05-16 10:12:26 start -->
2012-05-16 10:12:38 shutdown_func -->
2012-05-16 10:12:38 start -->
2012-05-16 10:12:48 shutdown_func -->
2012-05-16 10:12:48 start -->
2012-05-16 10:12:58 shutdown_func -->
2012-05-16 10:12:58 start -->
2012-05-16 10:13:08 shutdown_func -->
2012-05-16 10:13:08 start -->
2012-05-16 10:13:18 shutdown_func -->
2012-05-16 10:13:18 start -->
2012-05-16 10:13:28 shutdown_func -->
2012-05-16 10:13:28 start -->
2012-05-16 10:13:40 shutdown_func -->
2012-05-16 10:13:40 start -->
2012-05-16 10:13:50 shutdown_func -->
2012-05-16 10:13:50 start -->
2012-05-16 10:14:02 shutdown_func -->
2012-05-16 10:14:02 start -->
2012-05-16 10:14:14 shutdown_func -->
2012-05-16 10:14:14 start -->
2012-05-16 10:14:26 shutdown_func -->
2012-05-16 10:14:26 start -->
2012-05-16 10:14:36 shutdown_func -->
2012-05-16 10:14:36 start -->
2012-05-16 10:14:48 shutdown_func -->
2012-05-16 10:14:48 start -->
2012-05-16 10:14:58 shutdown_func -->
2012-05-16 10:14:58 start -->
2012-05-16 10:15:08 shutdown_func -->
2012-05-16 10:15:08 start -->
2012-05-16 10:15:18 shutdown_func -->
2012-05-16 10:15:18 start -->

php_errors.log

[16-May-2012 02:11:54 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:04 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:14 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:26 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:38 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:48 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:12:58 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:13:08 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:13:18 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:13:28 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:13:40 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:13:50 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:02 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:14 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:26 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:36 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:48 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:14:58 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:15:08 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:15:18 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:15:28 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 41
[16-May-2012 02:15:28 UTC] PHP Fatal error:  Maximum execution time of 10 seconds exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 33

看起来关闭功能被调用了大约 22 次,但突然没有被调用。

我的 php 版本是 5.3.9,服务器是 IIS 7.5 真的需要一些帮助!非常感谢!

------------------------更新1------------- ------------------

经过一番挖掘,我在 php 源代码中找到了一个测试脚本。看起来注册的关闭功能可能会超时。

<?php
set_time_limit(1);
register_shutdown_function("plop");

function plop() {
    $ts = time();
    while(true) {
        if ((time()-$ts) > 2) {
            echo "Failed!";
            break;
        }
    }
}
plop();
?>

结果是:

Fatal error: Maximum execution time of 1 second exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 9

Fatal error: Maximum execution time of 1 second exceeded in E:\eclipse_php_workspace\caijiche_new2\t.php on line 9
4

1 回答 1

0

从开始到结束需要 12 秒(请参阅 zz.txt 中的计时器),最大执行时间设置为 10 秒。所以有问题。

通常我将时间限制截止时间设置为(最大执行时间 - 5 秒),但由于您只有 10 秒和 2 秒的覆盖时间,因此您应该将关闭时间设置为 7 秒。


如果您从浏览器启动它,则可能优先从 META Refresh 指令实际执行“调用自身”。通过这种方式,您可以发出一个带有状态和元刷新的小型 HTML 页面。(这也是我的首选路线!)如果您不是从浏览器运行 cron 或其他后端进程,请忽略。


编辑(以节省输入太多评论)以响应“它现在已停止,但几分钟后又回来了”。

我的猜测是,如果你仍然有 PHP 脚本调用自己,它可能会消耗越来越多的内存,并且永远不允许 iteslf 进行垃圾收集。Apache 中的每个 PHP 脚本需要大约 10MB 的 Apache 开销,再加上另外 2-3MB 的 PHP 脚本 - 所以你调用自己的次数越多,它就会越加并最终变慢。

所以你需要回到其中一个建议:

a) 如果从浏览器调用,与 PHP 调用自身相反,发出

<html>
   <head>
      <meta http-equiv="refresh" content="1; url=http://127.0.0.1/t.php">
   </head>
   <body>
     Echo going to <a href="http://127.0.0.1/t.php">http://127.0.0.1/t.php</a>
   </body>
</html>

这意味着在 PHP 脚本中有调用自身;PHP 也可以呼吸并且可以收集垃圾,尽管只运行一个简单的脚本就不需要中断 - 停止循环应该可以解决它。

问题:如果你的连接失败,或者互联网失败,那么响应将不会发生并且脚本会中断,所以:

b) 一种变体是创建一个每 10 秒调用一次服务器的 javascript。超时后不要做任何事情,因为 Javascript 只会再次启动该过程。

c) 最好的方法是,如果您希望它“永远”运行,请从 cron 作业将 PHP 脚本作为命令行 (php -q /var/www/html/Myphp.php > /dev/nul) 运行。将 cron 作业设置为每分钟运行一次。向脚本添加一个计数器,该计数器在每次调用自身时递增,然后在第 6 次调用(即 1 分钟)后停止。这样,在脚本终止并允许自己被清理之前,您最多循环 5 次。

d) 或者,如果您可以编写一个快速的 shell 脚本,只需创建调用 PHP 命令行的 shell 脚本,然后等待 10 秒并再次调用它,共 6 次。从每分钟运行的 cron 触发该脚本。这样,您就没有 Apache 开销(节省套接字、节省内存)以及避免 lopping 问题。

e)还有其他变化 - 取决于您在服务器上获得的权限......

不保证他们会解决你的问题,但是一个无休止地调用自己的函数正在编程禁止,所以我至少会给第一个刺穿,看看它是否有效,然后研究更复杂的。

于 2012-05-16T04:30:46.343 回答