2011-08-25 39 views
3

我正在使用supervisor(http://supervisord.org/)来守护一个相当标准的PHP脚本。该脚本的结构是这样的:如何检测PHP CLI脚本处于挂起状态

while (1) { 
// Do a SQL select 
// for any matching rows, do something 
// if I have been running for longer than 60 mins, exit 
} 

今天,这个脚本(它已经相当稳定一段时间了)挂起。它没有崩溃(即发出SIGHUP或者SIGTERM信号),这会提醒supervisord重启该过程。它在处理过程中没有遇到任何错误,这些错误或者被脚本捕获,或者至少引发了致命的错误并退出。而不是这些“可捕捉”的场景,它只是坐在那里。我们确实有一个cron作业设置,每小时运行一次以通过supervisorctl钩子重新启动脚本,因为似乎普遍认为PHP脚本在内存方面存在漏洞,如果长时间运行,很可能会重新启动。重启后,脚本正常恢复运行。

我的问题:我如何检测到这个脚本已经挂起?我甚至无法开始诊断或解决这个问题,为什么它挂起,如果我不知道该状态的警报。我正在寻找这方面的软件解决方案,或者我可以采用一些方法来自己编写解决方案(无论是PHP,Python,Perl还是shell)。

该脚本使用PHP 5.2.6编写,并在最新的RHEL 5服务器上运行。

请让我知道,如果我可以分享任何额外的信息,如果它可以帮助一个更真棒的解决方案。

谢谢!

Shaheeb R.

回答

2

由于这是脚本挂起的情况,因此PHP可能不会处理任何可以检测到此挂起的附加代码。出于这个原因,我建议修改脚本以保存日志。这将允许主脚本让它外的任何东西知道它仍然在运行,并且有一些很好的更新,它还可以帮助查明事情发生错误的地方。

可以将日志记录写入文件或数据库,并且应至少包含脚本状态的指示符,例如上次修改日期。如果这个脚本没有持续运行,那么还应该指出它正在运行或已经停止。在你给出的例子中,日志写入会在while循环内至少发生一次,可能更多。它需要花费时间/资源来打开指针或数据库连接,所以我建议只记录需要的内容。 (注意:如果使用文本文件的方法,该文件将需要在每次写入后立即被关闭。)

例子:

while (1) { 
    log('Running SQL select'); 
    // Do a SQL select 
    log('Results retrieved'); 
    // for any matching rows, do something 
    // (check log) if I have been running for longer than 60 mins, exit 
} 

function log($msg) { 
    // Write timestamp, $msg to log 
} 

一个单独的脚本将需要检查的日志和报告任何错误,如果它受到主要剧本悬念的影响,这可能会有问题,但我无法想到替代方案。

关于记忆,如果你还没有使用mysql_free_result你应该试试看。

+0

mysql_free_result是defini非常有趣,以前没有遇到过。关于您建议尝试从外部脚本记录和监视此日志:这对我们可能是可行的。我们已经在脚本中执行应用程序日志记录,因此它将构成日志观察器来监视它。 –

+0

作为日志观察者,我们取得了SEC(http://simple-evcorr.sourceforge.net/)的良好成功,我们可以使用此工具构建解决方案。我得说,我很希望有一个'现成的'解决方案! –

0

这很简单!只需计算从循环开始到当前执行点的时间差。

$starttime = microtime(true); 
while (1) 
{ 
    //Do your stuff here 
    //More SQL, whatever you need 


    //Put this at the end of the loop 
    $curtime = microtime(true); 
    $timetaken = $curtime - $starttime; 
    if($timetaken > (60 * 60)) 
    { 
     break; 
    } 
} 

microtime(true)将返回秒自Unix纪元,所以如果我们减去我们从当前时间开始的时间,我们有时间采取/经过,并退出循环,如果一切都结束了60*60秒。

+0

唯一的问题,我在这里看到如果在进行任何操作之前进程挂起...(即:代码停止执行) – Jakub

+0

也是如此,正如我在第一篇文章中所描述的那样,我们已经在计算时间来限制脚本的运行时间。 –

1

我的建议与@Shroder所描述的类似,但要稍微深入一点。每次运行时,你会创建一个日志/数据库记录,那么它将被加盖时间戳+事务感知(你会更新在运行开始时的交易processing,然后做的时候,签署了与completed的条目。

在侧你会运行一个简单的cron检查,看看当前的时间比你触发大(60分钟,等)使用时间戳和交易状态。在这一点上你扔警报等;

+0

我喜欢在日志中包含事务状态的想法。这个“最终交易”令牌可能是日志观察者可以追踪的东西。也许在end-tx令牌之间设置一段时间间隔,如果超过该间隔,则强制重新启动脚本。 –

+0

@Shaheeb Roshan,如果你喜欢答案,不要忘记把upvote或标记为答案(绿色选中标记) – Jakub

相关问题