调试长时间运行的PHP脚本

ts.*_*ts. 14 php linux debugging

我有一个PHP脚本作为一个cron作业运行,广泛使用第三方代码.脚本本身有几千个LOC.基本上它是数据导入/处理脚本.(JSON到MySQL,但它也会产生大量的HTTP调用和一些SOAP).

现在,性能随着时间的推移而降级.使用少量记录(大约100)进行测试时,性能良好,可在10-20分钟内完成.当运行整个导入(大约1600条记录)时,一条记录的平均导入时间稳步增长,整个过程需要超过24小时,因此至少比预期长5倍.

内存似乎不是问题,使用量增长应该没有意外的峰值.

所以,我需要调试它以找到瓶颈.它可能是脚本,底层代码库,php本身,数据库,操作系统或网络部分的一些问题.我现在怀疑某种缓存在某个地方,这种缓存在接近100%的错失率方面表现不佳.

我不能使用XDebug,配置文件增长得太快而无法治疗.

所以问题是:如何调试这种脚本?

PHP版本:5.4.41操作系统:Debian 7.8如有必要,我可以拥有root权限,并安装工具.但它是生产服务器,理想情况下调试不应该太扰乱.

cij*_*ani 14

是它可能您可以使用编制品(PHP调试脚本)

它是什么?Kint for PHP是一种旨在以绝对最佳方式呈现调试数据的工具.

换句话说,它是类固醇上的var_dump()和debug_backtrace().易于使用,但功能强大且可定制.您的开发工具箱的重要补充.

仍然输了?你用它来看看里面的变量是什么.

在此输入图像描述

充当debug_backtrace替换器 在此输入图像描述

你可以在这里这里下载

总文件和帮助在这里

此外,它还支持几乎所有的PHP框架

  • Drupal的
  • Symfony的
  • Symfony 2
  • WordPress的
  • 警予
  • 骨架
  • Zend框架

祝一切顺利.... :)


Gre*_*rdt 8

有三件事情会浮现在脑海中:

  1. 设置IDE,以便逐行调试PHP脚本
  2. 添加一些日志记录到脚本
  3. 在MySQL中查找长时间运行的查询

调试选项#2是最简单的.由于这是作为一个cron作业运行,你echo在脚本中添加了一堆:

<?php

function log_message($type, $message) {
    echo "[{strtoupper($type)}, {date('d-m-Y H:i:s')}] $message";
}

log_message('info', 'Import script started');

// ... the rest of your script

log_message('info', 'Import script finished');
Run Code Online (Sandbox Code Playgroud)

然后管道stdout到cron job命令中的日志文件.

01 04 * * * php /path/to/script.php >> /path/to/script.log
Run Code Online (Sandbox Code Playgroud)

现在,您可以添加log_message('info|warn|debug|error', 'Message here')整个脚本,至少可以了解性能问题的位置.

调试选项#3只是MySQL中的直接调查工作.您的一个查询可能需要很长时间,并且它可能会出现在MySQL的长期运行查询实用程序中.


hek*_*mgl 6

用于strace从系统角度查看程序基本上正在执行的操作.是否挂在IO操作等?strace应该是遇到任何类型的Linux应用程序的性能问题时尝试的第一件事.没人能躲避它!;)

如果您发现该节目在网络相关的调用像挂起connect,readfrom和朋友,这意味着网络通信并挂在某个点,同时连接或等待响应比你可以使用tcpdump来分析这一点.

使用上述方法,您应该能够找到最常见的性能问题.需要注意的是,你甚至还可以连接到正在运行的任务与strace使用-p PID.


如果上述方法没有帮助,我会使用xdebug来分析脚本.您可以使用类似工具分析探查器输出KCachegrind


Fab*_*ler 6

分析工具:

有一个名为Blackfire的PHP分析工具,目前处于公开测试阶段.有关如何配置CLI应用程序的特定文档.收集配置文件后,您可以在一个漂亮的用户界面中通过时间测量来分析应用程序控制流: 黑火工具

内存消耗可疑:

内存似乎不是问题,使用量增长应该没有意外的峰值.

不断增长的内存使用率听起来很可疑!如果当前数据集不依赖于导入的所有先前数据集,那么增长的内存很可能意味着所有导入的数据集都保存在内存中,这很糟糕.PHP也可能经常尝试垃圾收集,只是为了发现没有什么可以从内存中删除.特别是长时间运行的CLI任务会受到影响,因此请务必阅读发现该行为的博客文章.


Cup*_*ups 5

虽然没有规定,如果我的猜测是正确的,你似乎一次只处理一个记录,但是在一个大的cron中.

即抓住一个记录#1,以某种方式捣乱它,为它增加价值,重新格式化然后保存它,然后移动到记录#2

我会考虑打破这个大cron.即

Cron#1:获取所有记录,并在本地缓存所有显着数据(到该服务器).如果达到此阶段,请设置标志.

Cron#2:现在你拥有了你需要的数据,munge和add value,缓存那个输出.如果达到此阶段,请设置标志.

Cron#3:重新格式化数据并存储它.删除所有文件.

这种"分而治之"将缓解你的调试困境,并导致更好地了解实际发生的事情,并作为奖励让你有机会重新运行说,cron 2.

我必须多次这样做,对我而言,日志记录是识别代码中的弱点,识别关于数据质量的不良假设的关键,并且可以暗示延迟导致问题的位置.