Получение вывода дочернего процесса "PHP Fatal Error" - PullRequest
2 голосов
/ 25 марта 2011

Я уже узнал, что вы не можете перехватить фатальные ошибки PHP, и ваш скрипт завершит работу, как только он попадет в него. Я запускаю большой набор тестов PHP (не PHPUnit, а собственное решение) на CI-сервере и хочу, чтобы результаты тестов / неудач сообщались в формате вывода JUnit.

Поскольку слишком много вещей в PHP являются «фатальными ошибками», я не хочу, чтобы фатальная ошибка заканчивала мой тестовый запуск, поэтому я решил использовать разветвление, что-то вроде этого:

foreach($tests as $test) {
    $pid = pcntl_fork();
    if ($pid) {
        $test->run();
        $test->write_junit($some_file_name);
    }
    else {
        pcntl_wait($status);
        if ($status) { //fatal error
            // from here we have no data about why it 
            // crashed, since that was in the child's memory
        }
    }
}

Моя идея заключалась в том, чтобы закрыть STDERR в дочернем элементе и отправить его стандартную ошибку в канал, который родитель может прочитать и сохранить данные об ошибках в файл JUnit, но теперь я не знаю, возможно ли это. Можете ли вы изменить файл для STDERR? По сути, я хочу сделать что-то вроде popen , но без шага exec ().

Можно ли получить выходные данные дочернего процесса после его смерти от PHP-фатальной ошибки?

Ответы [ 2 ]

1 голос
/ 19 мая 2011

Вы можете зарегистрировать функцию отключения в дочернем процессе и проверить последнюю ошибку при ее вызове.Если есть ошибка, соответствующая одному из фатальных типов (E_ERROR, E_COMPILE_ERROR, E_CORE_ERROR и E_PARSE), запишите ее в файл JUnit.Хотя вы не можете восстановить из-за фатальной ошибки, ваша функция отключения по-прежнему вызывается.

Обновление: Как отметил Пейсер в комментариях, поскольку E_CORE_ERROR толькоБрошенный во время самозагрузки интерпретатора PHP происходит до того, как функция завершения работы может быть зарегистрирована и не может быть перехвачена.

0 голосов
/ 25 марта 2011

Я не смог найти ничего, что позволило бы вам перенаправить stderr с помощью подхода, подобного тому, который вы используете.

Однако, возможно, вы могли бы использовать ini_set('error_log', $some_log_path) в вашем ребенке, а затем прочитать файл, если ребенок упал, чтобы определить сообщение об ошибке?

Если это не удастся, вы можете переписать свой код, чтобы вызвать отдельную оболочку PHP для одного запускающего теста через proc_open и использовать оболочку для отправки stderr куда-то в здравом уме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...