如何在 laravel 控制台命令中显示异常跟踪


How can I display Exception trace in laravel console command?

我正在使用Laravel 5.1来创建基于控制台的应用程序。在开发过程中,我想在发生错误时显示异常跟踪。但是,即使我在 php artisan 中使用 -v -vv 或 -vvv 选项,我也不会获得自定义命令的异常跟踪。我在.env中设置了APP_DEBUG=true,仍然没有异常痕迹。

php artisan some:unknowncommand的输出为:

[InvalidArgumentException]                              
There are no commands defined in the "some" namespace.

php artisan -v some:unknowncommand的输出为:

[InvalidArgumentException]                              
  There are no commands defined in the "some" namespace.  
Exception trace:
 () at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:501
 Symfony'Component'Console'Application->findNamespace() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:535
 Symfony'Component'Console'Application->find() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:192
 Symfony'Component'Console'Application->doRun() at /Users/dirkpostma/Dropbox/Domains/dpepp/vendor/symfony/console/Application.php:126
...

现在,我创建了一个非常简单的控制台命令,称为 dp:test,具有以下句柄函数:

/**
 * Execute the console command.
 *
 * @return mixed
 */
public function handle()
{
    generate error here
}

php artisan dp:test的输出为:

[Symfony'Component'Debug'Exception'FatalErrorException]
syntax error, unexpected 'error' (T_STRING)    

php artisan -v dp:test的输出是相同的。php artisan -vvv dp:test的输出是相同的。

日志文件确实显示了异常跟踪,因此应该可以在 cli 中显示它。我什至没有看到发生错误的文件名和行号......我该如何处理?

提前感谢!

编辑:

被挖得更远了。如果我在我的命令中使用它:

public function handle()
{
    throw new 'Exception("test exception");
}

我发出命令php artisan -v dp:test,错误跟踪是打印的。仅当由于 PHP 错误引发异常时,才会打印跟踪。在Illuminate/Foundation/Bootstrap/HandleExceptions.php方法中bootstrap PHP 错误被转换为异常。发生这种情况时,将引发异常,但在打印时会以某种方式忽略 -v。这非常不方便,因为它使调试 CLI 应用程序变得困难。

我认为解决方案可以在vendor/symfony/console/Application.php,方法renderException中找到。

稍后会进一步挖掘,除非其他人可以比我更快地指出解决方案:-)

我找到了忽略-v的原因:

Illuminate/Foundation/Bootstrap/HandleExceptions.php 中,renderForConsole 方法使用默认设置实例化ConsoleOutput对象,而不考虑用户要求的详细程度设置:

protected function renderForConsole($e)
{
    $this->getExceptionHandler()->renderForConsole(new ConsoleOutput, $e);
}

因此,无论设置什么 -v -vv 或 -vvv,vendor/symfony/console/Application.php 中的$output->getVerbosity()始终低于 OutputInterface::VERBOSITY_VERBOSE ,因此,不会打印堆栈跟踪。

我可能会为此在 github 上启动一个问题,因为我认为如果用户设置 -v,如果在 CLI 中显示错误会更方便。

您可以通过添加以下 use 语句将详细程度设置为所需的任何级别:

use Symfony'Component'Console'Output'OutputInterface;

然后将其添加到句柄函数的顶部:

$this->output->setVerbosity(OutputInterface::VERBOSITY_VERY_VERBOSE);

请参阅symfony控制台的文档 这里 http://symfony.com/doc/current/console/verbosity.html了解更多信息。

如果您查看Illuminate'Console'Command类,您将看到将错误字符串写入控制台的函数的定义:

/**
 * Write a string as error output.
 *
 * @param  string  $string
 * @return void
 */
public function error($string)
{
    $this->output->writeln("<error>$string</error>");
}

现在你看到它只写入错误字符串,你可以用它玩一点来实现你想要的。您可以获取函数回调跟踪,并根据需要向后输出任意数量的行和文件。只需创建扩展命令的类,覆盖函数并使所有命令继承该命令类:

/**
 * Write a string as error output.
 *
 * @param  string  $string
 * @return void
 */
public function error($string)
{
    $this->output->writeln("<error>$string</error>");
    $trace = debug_backtrace();
    foreach ($trace as $t) 
    {
        $this->output->writeln("Trace : " . $t['file'] . " on line " . $t['line'] . " function " . $t['function']);
    }
}