代码之家  ›  专栏  ›  技术社区  ›  Nate Weiner

查找PHP脚本终止源的最佳实践

  •  6
  • Nate Weiner  · 技术社区  · 15 年前

    我有一个PHP脚本,它从数据库中获取一块数据,对其进行处理,然后查看是否有更多数据。这个进程无限期地运行,我在一台服务器上一次运行几个进程。

    它看起来像:

    <?php
        while($shouldStillRun)
        {
           // do stuff
        }
        logThatWeExitedLoop();
    ?>
    

    问题是,一段时间后,某个原因导致进程停止运行,我无法调试它并确定原因。

    以下是我目前用来获取信息的方法:

    • 错误日志 -记录所有错误,但错误日志中不显示任何错误。
    • 寄存器关闭功能 -注册了自定义关机功能。这会被调用,所以我知道进程不会被服务器终止,而是被允许完成。 (或者至少我认为这就是所谓的情况?)
    • 调试回溯 -在我的自定义关机函数中记录了一个debug_backtrace()。这只显示了一个调用,这是我的自定义关机功能。
    • 如果到达脚本末尾,则记录日志 -在循环之外,我有一个函数记录脚本退出循环(因此通常会到达源文件的末尾)。当脚本随机死亡时,它不记录这个,所以无论杀死它,杀死它在处理的中间。

    为了找到罪魁祸首,您建议使用哪些其他调试方法?

    注意:我应该补充一点,这不是最大执行时间的问题 ,这对这些脚本是禁用的。被杀前的时间不一致。它可以在死亡前运行10秒或12小时。


    更新/解决方案 :谢谢大家的建议。通过记录输出,我发现当MySql查询失败时,脚本被设置为die()。哦。更新它以记录mysql错误,然后终止。现在它像个符咒一样工作了!

    6 回复  |  直到 15 年前
        1
  •  2
  •   Kamil Szot    15 年前

    我会记录你脚本的内存使用情况。也许它获取了太多的内存,达到了内存限制,然后就死了?

        2
  •  2
  •   Rahly    15 年前

    记住,PHP在ini文件中有一个变量,表示脚本应该运行多长时间。 max-execution-time

    请确保您没有超过这一步,或者使用set_time_limit()来增加执行时间。该程序是通过web服务器运行还是通过cli运行?

    添加: 我在PHP方面的糟糕经历。看看我今年早些时候写的一些背景脚本。抱歉,PHP是一种糟糕的脚本语言,它可以长时间执行任何操作。我看到新的PHP(我们还没有升级到)添加了强制GC运行的功能。我遇到的问题是使用了太多内存,因为GC几乎从不运行来清理自己。如果你使用递归引用自身的东西,它们也永远不会被释放。

    创建一个包含100000个项目的数组会增加内存,但将数组设置为空数组或将其全部拼接,不会立即释放它,也不会将其标记为未使用(也就是说,创建一个新的100000个元素数组会增加内存)。

    我个人的解决方案是编写一个永远运行的perl脚本,然后运行系统(“php My_php.php”);必要时,让口译员完全自由。我目前支持5.1.6,这可能在5.3+中得到修复,或者至少,现在他们有GC命令,可以用来强制GC清理。

    简单脚本

    #!/usr/bin/perl -w
    
    use strict;
    
    while(1) {
      if( system("php /to/php/script.php") != 0 ) {
        sleep(30);
      }
    }
    

    然后在php脚本中

    <?php
    
    // do a single processing block
    
    if( $moreblockstodo ) {
      exit(0);
    } else {
      // no? then lets sleep for a bit until we get more
      exit(1);
    }
    
    ?>
    
        3
  •  0
  •   JAL    15 年前

    我会将函数的状态记录到每个循环中几个不同位置的文件中。

    您可以使用 var_export ,使用 var_export($varname,true) 类型

    你可以把它记录到一个特定的文件中,并密切关注它。日志结束前函数的最新状态应该提供一些线索。

        4
  •  0
  •   Steve    15 年前

    听起来,无论发生什么都不是标准的php错误。你应该能够通过尝试抛出自己的错误。。。然后应该记录的catch语句。除此之外,我没有更多的细节,因为我的手机远离电脑。

        5
  •  0
  •   Nikko    15 年前

    我以前在工作中的一个项目中遇到过这种情况。我们有一个类似的设置——一个PHP脚本检查数据库是否有任务要完成(比如发送电子邮件、更新记录、处理一些数据)。PHP脚本内部有一个while循环,设置为

    while(true) {
        //do something
    }
    

    过了一段时间,剧本也会以某种方式被扼杀。我已经尝试过这里所说的大部分内容,比如设置max_execution_time、使用var_export记录所有输出、放置try_catch、生成脚本输出(php…>output.txt)等等,但我们始终无法找出问题所在。

    我认为PHP本身并不是用来做后台任务的。我知道它没有回答你的问题(如何调试),但我们的工作方式是,我们使用cronjob每5分钟调用一次PHP文件。这类似于Jeremy使用perl脚本的回答——它确保了解释器在执行完成后是空闲的。

        6
  •  0
  •   Piskvor left the building Rohit Kumar    15 年前

    如果是在Linux上,请尝试查看系统日志——进程可能会被OOM(内存不足)杀手(不太可能,如果发生这种情况,您还会看到其他问题)或分段错误(某些版本的PHP不喜欢某些版本的扩展,导致奇怪的崩溃)杀死。

    推荐文章