【问题标题】:PHP cron job premature termination due to Maximum execution time fatal error由于最大执行时间致命错误,PHP cron 作业提前终止
【发布时间】:2012-03-19 17:21:54
【问题描述】:

我有一个 PHP cron 作业在运行 29 分钟后失败。日志中的错误(/var/log/php_errors.log)是:

[01-Mar-2012 00:32:57 UTC] PHP Fatal error: Maximum execution time of 60 seconds exceeded in /path/file.php on line 2079

触发 cron 的 crontab 条目是:

00 00 * * * /usr/bin/php /path/file.php

根据我的研究,我认为这与 max_execution_time 配置设置无关,因为:

  1. 我知道它运行了 29:18 分钟(即像错误消息一样超过 60 秒)。
  2. 来自the PHP docs - 从命令行运行 PHP 时,默认设置为 0。

问:为什么脚本会提前终止?


注意事项:

脚本非常繁重,确实运行了数千个数据库查询,但我运行的是top,CPU 负载并不高。

错误日志中的行是mysql_query 调用:

$sql = "SELECT SUM(amount) FROM mytab WHERE mem = '$id' AND validto > '$now'";
$res = mysql_query($sql);

> php -v
PHP 5.3.10 (cli) (built: Feb  2 2012 17:34:38) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.3.0, Copyright (c) 1998-2012 Zend Technologies
    with Suhosin v0.9.33, Copyright (c) 2007-2012, by SektionEins GmbH

> cat /etc/redhat-release
Red Hat Enterprise Linux Server release 5.7 (Tikanga)

更新 - 我发现了为什么脚本可以实时运行 29 分钟,但 PHP 可以退出引用执行时间要短得多。

在确定脚本运行的最长时间时,不包括在脚本执行之外发生的活动所花费的任何时间,例如使用 system() 的系统调用、流操作、数据库查询等。

p>

(来自the set_time_limit() docs,但也提到了the max-execution-time docs)。这对我来说很重要,因为大部分脚本都是长时间运行的数据库查询和支付 API 调用,它们不会计时执行时间。

【问题讨论】:

  • cron 作业与您的错误无关,这是一个纯 PHP 问题。检查内存泄漏,在执行循环后尝试取消设置一些错误数组。在查询之间释放其他大变量。
  • 您还会在文档中注意到它说:最大执行时间不受系统调用、流操作等影响。你能确定它实际上是由 cron 触发的 PHP CLI 吗?
  • 我还会检查您是否有合适的索引来加快选择速度。你有关于 memvalidto 的索引吗?
  • 谢谢。我通过手动从 CLI 触发它来验证它正在使用 PHP CLI,得到了同样的错误。我确实有索引,查询非常快(没有 mysql 慢日志条目),但是这些查询有很多(例如 200,000)。

标签: php cron fatal-error


【解决方案1】:

如果你得到PHP Fatal error: Maximum execution time of 60 seconds exceeded,那么肯定一些 段正在运行的PHP 代码会在某处运行语句set_time_limit(60)。 PHP CLI 模式可能默认为无时间限制,但如果 any 代码路径曾经设置时间限制,它将被兑现。 PHP 确实运行了近半小时的原因是因为set_time_limit 设置了 CPU 时间限制,如果该进程受到 I/O 限制或等待其他进程,则总 CPU 使用率将在很久以后达到 60 秒大关时钟。

尝试在您的所有源代码中搜索set_time_limit。如果您没有找到任何内容,请在脚本开头添加 set_time_limit(0) 以确保 60 秒限制不是来自本地修改的配置文件。例如,在 Ubuntu LTS 上,PHP CLI 配置在 /etc/php5/cli/php.ini 中定义。

【讨论】:

  • 谢谢。有用的信息。寻找set_time_limit 发现了问题。
【解决方案2】:

很遗憾我不能写评论,所以我的问题是,如果你手动运行会发生什么?也会超时吗?

如果你手动运行它没有超时,我建议你调用一个小shell脚本,它实际上运行一个shell并在shell中运行“/usr/bin/php /path/file.php” .

00 00 * * * /usr/local/scripts/start_php_job.sh

File: /usr/local/scripts/start_php_job.sh
#!/usr/bin/bash
date

/usr/local/bin/php /path/to/script

date

【讨论】:

  • 谢谢。我尝试从命令行手动运行它,并得到与通过 cron 自动触发时相同的错误。
  • 可以记录运行过程中的内存消耗吗?你的“资源限制(ulimit -a)是多少?我假设如果它像这样停止,缓冲区缓存已满,用户最大内存使用量、sql-server 最大内存使用量或系统内存达到最大值。我建议你做一个 ps -uef (我认为这也是显示内存的那个)并 grep 你的进程,每 5 秒执行一次。return 代码实际上是什么也很好. 如果你在上面描述的 shellscript 中运行它,你可以通过 echo $? 得到错误代码,它会显示出来,也许这会给你更多的提示。
【解决方案3】:

嗯,你可以设置一个更大的时间限制值,或者你可以使用set-time-limit()将它设置为无限:

<?php set_time_limit(0); ?>

但实际上我在脚本开头也使用了它

ignore_user_abort(1);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多