2012-02-16 2 views
11

Почему ошибки из консольных задач не регистрируются. Например Exception на предупреждения PHP:Symfony 2 Исключение регистрации в консоли

[ErrorException]
Notice: Undefined offset: 1 in /var/www/project/vendor/doctrine/lib/Doctrine/ORM/Query.php line 298

Я понимаю, что печатается в стандартный вывод, но ничего не записывается в журналы. (Я использую консольные команды в cron). В Интернете эти исключения регистрируются с обратной сетью, которая в этой ситуации более информативна, чем просто это исключение.

В качестве решения: Я прилагаю все функции процесса в файле try..catch и регистрирую обратную трассировку вручную.

Кто-нибудь знает, как включить или настроить ведение журнала в консольных задачах. Я думаю, что это должно быть где-то.

ответ

14

Поскольку я следил за кодом, на самом деле нет такой возможности, чтобы включить ведение журнала для команд. В app/console этот код:

use Symfony\Bundle\FrameworkBundle\Console\Application; 

... 

$application = new Application($kernel); 
$application->run(); 

Он называет Symfony\Component\Console\Application::run(), в котором есть попытаться/поймать блок. По методу исключения вызывается renderException(), но никаких протоколов не происходит нигде.

Также обратите внимание, что app/console всегда по умолчанию выходит с кодом ошибки при исключении.

Вы можете создать свой собственный Application класс, распространяемый Symfony\Bundle\FrameworkBundle\Console\Application, и изменить app/console, чтобы использовать его. Чем вы можете переопределить метод run() и добавить журнал ошибок.

Или вы можете изменить только app/console и обрабатывать erros, как это:

// $application->run(); 
$application->setCatchExceptions(false); 
try { 
    $output = new Symfony\Component\Console\Output\ConsoleOutput(); 
    $application->run(null, $output); 
} catch (Exception $e) { 
    ... error logging ... 

    $application->renderException($e, $output); 

    $statusCode = $e->getCode(); 
    $statusCode = is_numeric($statusCode) && $statusCode ? $statusCode : 1; 
    exit($statusCode); 
} 
+0

Спасибо за разъяснение. Я копаю в консоль запуска файлов и index.php, но должен копать глубже в классе Application. Но кажется, что классы приложений в веб-и консолях имеют одинаковое поведение. – Sawered

2

Другой способ реализовать свой собственный пользовательский OutputInterface класс и переопределить метод writeln для входа ошибку там. Затем используйте новый класс при выполнении метода run().

Таким образом, вы можете придерживаться Open/Close Principle Symfony без необходимости изменять базовые классы и достичь своих целей.

6

TL; DR: просто использовать this bundle

От cookbook:

Чтобы получить консольное приложение для автоматического входа пойманных исключений для всех ваших команд, вы можете использовать консольные события.

Создание службы помечена как слушатель событий для console.exception события:

# services.yml 
services: 
    kernel.listener.command_dispatch: 
    class: Acme\DemoBundle\EventListener\ConsoleExceptionListener 
    arguments: 
     logger: "@logger" 
    tags: 
     - { name: kernel.event_listener, event: console.exception } 

Теперь вы можете делать все, что вы хотите с исключениями консолей:

<?php 
// src/Acme/DemoBundle/EventListener/ConsoleExceptionListener.php 
namespace Acme\DemoBundle\EventListener; 

use Symfony\Component\Console\Event\ConsoleExceptionEvent; 
use Psr\Log\LoggerInterface; 

class ConsoleExceptionListener 
{ 
    private $logger; 

    public function __construct(LoggerInterface $logger) 
    { 
    $this->logger = $logger; 
    } 

    public function onConsoleException(ConsoleExceptionEvent $event) 
    { 
    $command = $event->getCommand(); 
    $exception = $event->getException(); 

    $message = sprintf(
     '%s: %s (uncaught exception) at %s line %s while running console command `%s`', 
     get_class($exception), 
     $exception->getMessage(), 
     $exception->getFile(), 
     $exception->getLine(), 
     $command->getName() 
    ); 

    $this->logger->error($message); 
    } 
} 
+0

Да, поскольку Symfony 2.3 это лучшее решение. – Martin

6

Если это вопрос просто понимая, что пошло не так, вы можете запустить свое приложение с подробным флагом -v или --verbose, который будет automatically print the exception trace на экране.

+0

Вы правы, но вопрос заключался в написании ошибок для журнала (например, в файле) Это было необходимо, когда я запускал команды cli из cron – Sawered

+0

Правда, извините, пропустил часть cron. Не мог понять, как добраться до задней линии, не слишком усложняя ее, решил поделиться результатами. –

+1

@IanBytchek, спасибо, в любом случае, ваш ответ мне очень помог! –

Смежные вопросы