睡不着

时间:2015-08-05 16:06:40

标签: php

我的脚本检查HTTP服务器是否正在响应...它应该每隔60秒询问列表中的所有服务器。但它根本不会等待。知道为什么吗?它确实执行睡眠线(就像我在那里做回声一样,确实出现了),但是在那60秒内没有停止......只有在达到子限制时才会停止(在这种情况下 - 从不)。知道为什么吗?

PHP 5.4.41-0 + deb7u1

<?php

    echo "[".date("Y-m-d H:i:s")."] Starting...\n";

    declare(ticks = 1); // cpu directive

    error_reporting(0); // screw warnings
    set_time_limit(0); // no limits!

    $ctx = stream_context_create(array( // timeout file_get_contents context
        'http' => array(
            'timeout' => 30 // half of time between requests
            )
        )
    );

    $test_urls = array( // test urls
        'URL1' => 'http://www.google.com',
        'URL2' => 'http://www.ebay.de'
    );

    $max=10;
    $child=0;
    $rec_id=0;

    function sig_handler($signo) {
        global $child;
        switch ($signo) {
                case SIGCHLD:
                $child -= 1;
        }
    }

    pcntl_signal(SIGCHLD, "sig_handler"); // register fork signal handler to count running children

    $loop = 0;

    while (true){ // <main_loop>
    $loop++;

        foreach($test_urls as $uid => $url){ // <test_urls>

        echo "[".date("Y-m-d H:i:s")."] ENTERING LOOP:$loop\n";

            while ($child >= $max) {
                        sleep(1);
                    }

            $child++;
            $rec_id++;

            if($rec_id > 999999) $rec_id = 1; // limit rec_id, so it wouldn't cause an out of bounds error

            $pid=pcntl_fork();

            if($pid){

                // If you're here, something is totally messed up.

            }else{ // <fork>

                $req_start = microtime(true);
                $result = file_get_contents($url,NULL,$ctx);                
                $req_time = microtime(true) - $req_start;

                if($result) echo "[".date("Y-m-d H:i:s")."] OK - $req_time\n";
                else echo "[".date("Y-m-d H:i:s")."] ERROR - $req_time\n";

                sleep(1); // avoid segmentation fault, when fork ends before handling signals
                exit;

            } // </fork>

        } // </test_urls>

    echo "[".date("Y-m-d H:i:s")."] GOING TO SLEEP ON LOOP: $loop\n";
        sleep(60); // test every 60 seconds (if childs are available!)
    echo "[".date("Y-m-d H:i:s")."] WAKING UP LOOP: $loop\n";

    } // </main_loop>

    while($child != 0){
        sleep(1);
    }
?>

结果:*

[2015-08-05 18:17:43] Starting...
[2015-08-05 18:17:43] ENTERING LOOP:1
[2015-08-05 18:17:43] ENTERING LOOP:1
[2015-08-05 18:17:43] GOING TO SLEEP ON LOOP: 1
[2015-08-05 18:17:43] OK - 0.36189103126526
[2015-08-05 18:17:44] OK - 0.99003601074219
[2015-08-05 18:17:44] WAKING UP LOOP: 1
[2015-08-05 18:17:44] ENTERING LOOP:2
[2015-08-05 18:17:44] ENTERING LOOP:2
[2015-08-05 18:17:44] GOING TO SLEEP ON LOOP: 2
[2015-08-05 18:17:44] OK - 0.30263018608093
[2015-08-05 18:17:45] WAKING UP LOOP: 2
[2015-08-05 18:17:45] ENTERING LOOP:3
[2015-08-05 18:17:45] ENTERING LOOP:3
[2015-08-05 18:17:45] GOING TO SLEEP ON LOOP: 3
[2015-08-05 18:17:45] OK - 0.445955991745
[2015-08-05 18:17:45] OK - 1.2020018100739
[2015-08-05 18:17:45] WAKING UP LOOP: 3
[2015-08-05 18:17:45] ENTERING LOOP:4
[2015-08-05 18:17:45] ENTERING LOOP:4
[2015-08-05 18:17:45] GOING TO SLEEP ON LOOP: 4
[2015-08-05 18:17:46] OK - 1.0700960159302
[2015-08-05 18:17:46] OK - 0.5119640827179
[2015-08-05 18:17:46] WAKING UP LOOP: 4
[2015-08-05 18:17:46] ENTERING LOOP:5
[2015-08-05 18:17:46] ENTERING LOOP:5
[2015-08-05 18:17:46] GOING TO SLEEP ON LOOP: 5
[2015-08-05 18:17:46] WAKING UP LOOP: 5
[2015-08-05 18:17:46] ENTERING LOOP:6
[2015-08-05 18:17:46] ENTERING LOOP:6
[2015-08-05 18:17:46] GOING TO SLEEP ON LOOP: 6
[2015-08-05 18:17:47] OK - 0.43205118179321
[2015-08-05 18:17:47] WAKING UP LOOP: 6
[2015-08-05 18:17:47] ENTERING LOOP:7
[2015-08-05 18:17:47] ENTERING LOOP:7
[2015-08-05 18:17:47] OK - 1.3988509178162
[2015-08-05 18:17:47] GOING TO SLEEP ON LOOP: 7
[2015-08-05 18:17:47] OK - 0.59426283836365
[2015-08-05 18:17:47] WAKING UP LOOP: 7
[2015-08-05 18:17:47] ENTERING LOOP:8
[2015-08-05 18:17:47] ENTERING LOOP:8
[2015-08-05 18:17:47] GOING TO SLEEP ON LOOP: 8
[2015-08-05 18:17:47] OK - 1.2100639343262
[2015-08-05 18:17:47] OK - 0.5920991897583

1 个答案:

答案 0 :(得分:3)

sleep可以被信号中断,在这种情况下,它将返回剩余的秒数并且不会继续。它可能收到的一个信号是孩子在执行期间被杀死(SIGCHLD)。您可以检查sleep的返回值,以确定是否有信号中断它,但我猜它确实退出SIGCHLD

在linux机器上返回值will be the remaining seconds to sleep,这样你就可以将睡眠置于循环中并休眠直到剩余的秒数为0,或者是否存在其他类型的错误(由{{发出信号) 1}}回复)

这样的事情可能有用:

FALSE

另请注意,在您的原始代码中,您有一条评论说明:

$timeLeft = 60;
while ($timeLeft > 0) {
   $timeLeft = sleep($timeLeft);
}

实际上是fork完成后的父部分,因此每次都会实际执行分支。您可能想要更改此评论,因为它可能会让您或任何其他阅读代码的人感到困惑,或者只是通过// If you're here, something is totally f***ed up. *<-- Edited for family friendliness* 检查来完全删除