【问题标题】:php never ending loopphp永无止境的循环
【发布时间】:2014-09-05 03:03:56
【问题描述】:

我需要一个在 php 中自行执行的函数,无需 crone 的帮助。我想出了以下对我很有效的代码,但由于它是一个永无止境的循环,它会对我的服务器或脚本造成任何问题,如果是这样,请给我一些建议或替代方案。谢谢。

$interval=60; //minutes
set_time_limit(0);

while (1){
    $now=time();
    #do the routine job, trigger a php function and what not.
    sleep($interval*60-(time()-$now));
}

【问题讨论】:

  • 你想要一个 php 守护进程
  • 就我个人而言,我不会将 PHP 用于守护进程。您总是会遇到内存泄漏,并且必须每个月左右重新启动它。我建议使用不同的编译语言。
  • 作为您的 php 新手,也许您应该解释一下为什么需要这个,可能有一个更好的主意
  • @Dagon 我正在构建一个网络应用程序,它基本上每 15 分钟循环一次订单,并将其分配给一个免费的派送员

标签: php loops


【解决方案1】:

我们在实时系统环境中使用了无限循环,基本上是等待收到的短信然后处理它。我们发现这样做会使服务器资源随着时间的推移而变得密集,并且必须重新启动服务器才能释放内存。

我们遇到的另一个问题是,当您在浏览器中执行带有无限循环的脚本时,即使您点击了停止按钮,它也会继续运行,除非您重新启动 Apache。

    while (1){ //infinite loop
    // write code to insert text to a file
    // The file size will still continue to grow 
    //even when you click 'stop' in your browser.
    }

解决方案是在命令行上将 PHP 脚本作为守护程序运行。方法如下:

nohup php myscript.php &

& 将您的进程置于后台。

我们发现这种方法不仅占用内存较少,而且您还可以通过运行以下命令在不重新启动 apache 的情况下终止它:

kill processid

编辑:正如 Dagon 所指出的,这并不是真正将 PHP 作为“守护程序”运行的方式,但使用 nohup 命令可以被视为穷人将进程作为守护程序运行的方式。

【讨论】:

  • 从命令行调用 php 脚本不会使其成为守护进程
  • 这种过程是 Apache 和 PHP 做得不好的,但是像 node.js 这样的新技术做的 - IMO 这类任务不应该用 PHP 来完成,它不可避免地会回来咬你。
  • @Dagon 什么会让它成为守护进程?
【解决方案2】:

您可以使用time_sleep_until() 函数。它将返回 TRUE 或 FALSE

$interval=60; //minutes
  set_time_limit( 0 );
  $sleep = $interval*60-(time());

  while ( 1 ){
     if(time() != $sleep) {
       // the looping will pause on the specific time it was set to sleep
       // it will loop again once it finish sleeping.
       time_sleep_until($sleep); 
     }
     #do the routine job, trigger a php function and what not.
   }

【讨论】:

    【解决方案3】:

    在php中创建守护进程的方法有很多种,而且已经很久了。

    只是在后台运行一些东西并不好。例如,如果它试图打印一些东西并且控制台关闭,程序就会死掉。

    我在 linux 上使用的一种方法是在 php-cli 脚本中使用 pcntl_fork(),它基本上将您的脚本分成两个 PID。让父进程杀死自己,并让子进程再次分叉自己。再次让父进程杀死自己。子进程现在将完全分离,并且可以愉快地在后台闲逛,做任何你想做的事情。

    $i = 0;
    do{
        $pid = pcntl_fork();
        if( $pid == -1 ){
            die( "Could not fork, exiting.\n" );
        }else if ( $pid != 0 ){
            // We are the parent
            die( "Level $i forking worked, exiting.\n" );
        }else{
            // We are the child.
            ++$i;
        }
    }while( $i < 2 );
    
    // This is the daemon child, do your thing here.
    

    不幸的是,如果该模型崩溃或服务器重新启动,则无法自行重新启动。 (这可以通过创造力来解决,但是......)

    要获得重生的稳健性,请尝试使用 Upstart 脚本(如果您在 Ubuntu 上)。Here is a tutorial - 但我还没有尝试过这种方法。

    【讨论】:

    【解决方案4】:

    while(1) 表示无限循环。如果你想打破它,你应该按条件使用break。 例如,。

    while (1){ //infinite loop
        $now=time();
        #do the routine job, trigger a php function and what no.
        sleep($interval*60-(time()-$now));
        if(condition) break; //it will break when condition is true
    }
    

    【讨论】:

    • 其实我不想让它坏,我只想知道后果是什么。
    猜你喜欢
    • 2016-06-04
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-14
    • 2020-03-14
    • 1970-01-01
    • 2019-03-03
    相关资源
    最近更新 更多