【问题标题】:How to debug "Symfony\Component\Debug\Exception\FatalErrorException" errors in PHP (Laravel)?如何调试 PHP (Laravel) 中的“Symfony\Component\Debug\Exception\FatalErrorException”错误?
【发布时间】:2019-01-17 03:34:45
【问题描述】:

我收到有关客户遇到的许多错误的报告

Symfony\Component\Debug\Exception\FatalErrorException

最长执行时间超过 30 秒

我自己无法在本地计算机或生产服务器上复制它。这个 URL 遍布整个网站,所以,我猜它是全球性的,比如导致这种情况的中间件。

我正在使用Sentry.io 收集数据,但异常跟踪只有1 个条目指向Symfony 基本代码中的某个代码,最常见的是:

vendor/symfony/finder/Iterator/ExcludeDirectoryFilterIterator.php 在第 73 行

vendor/symfony/finder/Iterator/DateRangeFilterIterator.php 第 45 行

vendor/symfony/finder/Iterator/RecursiveDirectoryIterator.php 第 69 行

显然,似乎存在与文件系统相关的问题,但由于没有任何痕迹,我无法看到在站点代码中的何处查找错误。我猜这是某种无限循环或泄漏,但没有任何痕迹可以查看,也没有一致的方法来重现问题。

我应该如何寻找问题并调试它?

有没有我可以设置的设置,或者我可以使用/启用的工具?

【问题讨论】:

  • 当您说,I, myself, cannot replicate it on my local machine nor on the production server 您是否使用遇到问题的客户帐户进行了尝试。其中很多看起来像文件目录迭代,如果你允许他们上传或生成文件,他们可能有太多的文件,并且如果没有任何帐户,你将无法重现问题。只是一个想法。
  • 您可以访问命令行吗?如果是这样,您可以尝试 strace tecmint.com/…
  • @ArtisticPhoenix 是的,我尝试了各种会话变量(未登录,以不同用户身份登录)。系统中没有文件上传/生成,当用户尝试打开获取一些基本数据的最简单的页面时,错误随机发生。
  • @AdrianHernandez-Lopez 我会试一试,谢谢。
  • 错误消息通常可以追溯到调用所有函数/类字符串的主要代码段查找错误开始的位置,它几乎肯定会出现在您/某人编写的代码中不在 Symfony 代码库中

标签: php laravel symfony debugging timeout


【解决方案1】:

阅读您的聊天对话后,我看到您正在使用此.env 配置:

CACHE_DRIVER=file 
SESSION_DRIVER=file 

我认为这是问题所在……我解释得更好一点。

当你为缓存或会话使用file 驱动程序时,Laravel 将创建大量文件来存储用户会话数据或应用程序缓存数据...

如果您的电子商务正在增长并产生大量流量,那么性能可能会因为框架必须扫描大量文件而降低。

我认为这可能是两种可能的解决方案:

  • 您的生产环境必须升级(我不知道您的生产服务器规格或您是否有足够的资源)。
  • 文件驱动程序对于您的应用程序要求来说变得太慢了。

我通常使用redis 作为缓存和会话驱动程序,它速度更快,并且具有“智能缓存”的良好策略,这是一个很棒的工具。

如果可能的话,我认为您也应该尝试使用它。 Memcached 也可能是一个很好的解决方案。

【讨论】:

  • 这很有意义。我将尝试使用您和@elitepc 的答案 (register_shudown_function) 来解决我的问题,然后看看这会把我带到哪里,谢谢!
  • 问题是“如何在 PHP (Laravel) 中调试超时错误?”,应用程序应该使用这个配置 CACHE_DRIVER=file SESSION_DRIVER=file,当然最好使用 redis 但那是不是这里的问题...
【解决方案2】:

如果您不确定异常的原因,那么您可以通过两种方式处理它

1 增加请求超时 ini_set('max_execution_time', 60); //60 秒 = 1 分钟

2 用 try catch 包装你的代码

try{
  //logic goes here
}catch(\Excaption $e){
 Log::error($e->getMessage().' '. $e->getFile().' '. $e->getLine());
 return back()->with('error',$e->getMessage() );
}

【讨论】:

  • 1.我认为增加超时可能是一个临时解决方案,但不会解决根本原因。 2. 你的意思是包装整个应用程序(index.phpbootstrap.php)?如果是这样,那不会产生任何不同的结果,只是手动处理相同的异常。
【解决方案3】:

你能注册一个关机功能吗? 即使发生超时,也会调用关闭函数。有了它,您可以打印或保存您想要的日志文件。 我不确定是否有更好的方法可以在 laravel 中获取回溯,但我可能会在纯 php 中这样做(调用 debug_backtrace)。

<?php

function timedOut() {
    //save to a log file instead of printing
    var_dump(debug_backtrace());
}

register_shutdown_function("timedOut");

http://php.net/manual/en/function.register-shutdown-function.php

http://php.net/manual/en/function.debug-backtrace.php

【讨论】:

  • 不知道这一点,一定会试一试。谢谢!
【解决方案4】:

我不习惯 Laravel,但我遇到了这个问题,我使用 PHP 的 register_shutdown_function 解决了这个问题。

我发现它在跟踪随机发生的错误方面非常有用。 这就是我在代码中执行此操作的方式。你可以把它放在一个可以在每个页面上执行的通用文件中,index.php 对你来说是一个不错的选择,因为所有 Laravel 路由都通过它(我的假设)。

register_shutdown_function( "check_for_fatal" );

function check_for_fatal(){
    $time = time(); //time when this error occurred

    $error = error_get_last();
    if (in_array($error["type"], [E_ERROR, E_CORE_ERROR, E_RECOVERABLE_ERROR])){
        $email_body = [];
        $email_body[] = 'Date: ' . date('m-d-Y H:i:s', $time);
        ob_start();
        var_dump($error);
        $email_body[] = ob_get_clean();
        //include any other data as needed
        //$body[] = "add data as appropriate";

        //You can email it to yourself, but if there are lots of errors you will be bombarded with emails
        mail('your_email_address@example.com', 'Subject', implode("\r\n", $email_body));
       //or you can save this to some log file
    }
}

【讨论】:

    【解决方案5】:

    看起来 PHP 正在等待一些资源,例如。文件访问、数据库、邮件服务器(我认为是文件)。

    • 您是否尝试在一个会话中在多个选项卡上使用您的应用?
    • 您是否尝试过从多台机器登录同一个帐户?
    • 也许脚本的某些部分正在打开文件而不是关闭它?
    • 您是否跟踪了用户从打开网站开始的操作才发现此错误?
    • 检查您的生产数据库 - 连接限制可能非常小?

    编辑

    我看到您正在使用dannyvankooten/vat.php 库,它向外部服务发出一些请求。这可能是您的问题的根源。该库正在使用 curl 发出请求。作者正在设置CURLOPT_CONNECTTIMEOUT,但未设置CURLOPT_TIMEOUT,您的脚本有时会等待超过max_execution_time 设置限制的时间。

    【讨论】:

      【解决方案6】:

      我认为您现在不应该增加超时时间。如果您执行“尝试捕获”,您可能会了解潜在问题。如果不是,请检查在特定方法或类中执行的操作/功能。您可能正在查询一个巨大的表,并且可能试图使用这些信息。

      如果你这样做了

      \DB::listen(function ($sql) {
              var_dump($sql);
         });
      

      这将告诉您该操作正在运行多少查询

      【讨论】:

        【解决方案7】:

        没有办法在 try catch 中捕获它,因为它实际上是 PHP 错误而不是异常。

        为了能够对此进行调试,您有几个选择:

        1. 在代码中添加一些日志以识别超时的位置
        2. 您可以使用Laravel dump server package 转储日志。这实际上将与 Laravel 5.7 一起提供,但你现在可以随时添加包

        【讨论】:

          【解决方案8】:

          我安装了 laravel-debugbar。我认为它对你有帮助。

          composer 需要 barryvdh/laravel-debugbar 接下来打开 config/app.php 并在“providers”数组中添加:

          Barryvdh\Debugbar\ServiceProvider::class,
          

          在别名数组类中:

          'Debugbar' => Barryvdh\Debugbar\Facade::class,
          

          你可以查看

          Debugbar::measure('My long operation', function() {
          

          // 做某事... });

          【讨论】:

            【解决方案9】:

            您无法捕获 php 超时错误。当 php 解释器停止执行时会发生此错误。您只能增加时间限制,例如 ini_set('max_execution_time', 300) 或将长时间执行工作转换为 cron 作业,例如 laravel 任务计划。

            【讨论】:

              【解决方案10】:

              新的 sentry 版本将为您提供正确的堆栈跟踪。

              您必须使用 "getsentry/sentry-php" 版本 >= "2.0"

              【讨论】:

                【解决方案11】:

                老实说,最好的办法是安装 xdebug 并以老式方式对其进行调试,遍历整个请求以找到瓶颈并尝试找出它来自何处。 Laravel 以及其他框架旨在尽可能顺利地运行。如果您遇到任何此类错误,则意味着您可能只是编写了错误的代码。

                如果没有更多信息,也很难为您提供具体建议。我的建议是重新创建您的 Laravel 应用程序所面临的环境规范(您可以使用 Docker 或 Vagrant 或您想到的任何可行的方法),然后使用 xdebug 运行以找出问题所在。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2016-02-02
                  • 2020-05-28
                  • 2014-11-11
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-08-18
                  相关资源
                  最近更新 更多