Предотвращение вывода ошибок трассировки PHP при использовании пользовательского обработчика останова
Мне, должно быть, что-то не хватает в понимании обработки ошибок PHP, в частности, подавления их вывода. Когда возникает фатальная ошибка, я ожидаю, что моя функция обработчика выключения обработает ее изящно и завершит выполнение script. Это работает так, как ожидалось. Однако я не могу помешать PHP выводить информацию о фатальной ошибке.
Мой файл php.ini содержит следующие директивы:
error_reporting = E_ALL | E_STRICT
display_errors = Off
Я установил error_reporting
, чтобы сообщить обо всем, и я использую собственный обработчик ошибок для исключения исключений. Я ожидаю, что display_errors = Off
предотвратит отображение любых сообщений об ошибках.
В любом случае, когда возникает фатальная ошибка, пользовательский обработчик ошибок обходит (поскольку выполнение script выполняется немедленно) и выполняется обработчик завершения работы.
Теперь, на мой упрощенный код:
error_reporting(E_ALL | E_STRICT);
ini_set('display_errors', 'Off');
function shutdown_handler()
{
$err = error_get_last();
$fatal = array(E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR);
if ($err && in_array($err['type'], $fatal)) {
echo "\n\ntest fatal error output\n\n";
}
exit();
}
register_shutdown_function('shutdown_handler');
Чтобы протестировать его, я генерирую фатальную ошибку "Допустимый размер памяти":
// max out available memory
$data = '';
while(true) {
$data .= str_repeat('#', PHP_INT_MAX);
}
Поскольку у меня есть display_errors = Off
, я ожидаю, что это будет производить только следующий вывод (в соответствии с обработчиком выключения):
test fatal error output
Но вместо этого я продолжаю получать:
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2147483648 bytes) in /home/daniel/mydev/php/test0.php on line 24
PHP Stack trace:
PHP 1. {main}() /home/daniel/mydev/php/test0.php:0
PHP 2. str_repeat() /home/daniel/mydev/php/test0.php:24
test fatal error output
Что мне не хватает, что предотвратит вывод этой ошибки?
Заключение
Похоже, как @Cthos отметил, что "E_ERROR и display_errors не играют хорошо вместе".
Это также относится к E_PARSE (и я предполагаю E_CORE_ERROR/E_COMPILE_ERROR, но я не нарушил установку PHP, чтобы проверить его). Я полагаю, что имеет смысл, что PHP заставит трассировку ошибок в STDOUT в этих случаях, потому что если бы вы этого не сделали, вы, возможно, никогда не узнаете, если/почему все идет не так.
Таким образом, решение в этом случае будет:
- Как предложено @Cthos, отключите уведомления E_ERROR в php.ini:
error_reporting = (E_ALL & ~ E_ERROR)
или во время выполнения с помощью error_reporting(E_ALL & ~ E_ERROR);
- Обновите обработчик выключения, чтобы проверить, была ли последняя ошибка типа E_ERROR и выполните соответствующие действия, если это так.
Что касается других смертей, таких как E_PARSE, E_CORE_ERROR и т.д., вам просто нужно убедиться, что ваш код верен и что ваш PHP работает. Если вы попытаетесь отключить ошибки E_PARSE и обработать их в своей функции выключения, это не сработает, потому что ошибки синтаксического разбора не позволяют PHP так далеко заходить.
Итак, обновленный/рабочий обработчик завершения выглядит следующим образом:
error_reporting(E_ALL & ~ E_ERROR);
function shutdown_handler()
{
$err = error_get_last();
if ($err && $err['type'] == E_ERROR) {
$msg = 'PHP Fatal Error: '.$err['message'].' in '.$err['file'].
' on line '.$err['line'];
echo $msg, PHP_EOL;
}
exit();
}
Ответы
Ответ 1
Информация о нежелательной ошибке связана с конфигурацией регистрации ошибок (log_errors
и error_log
) и полностью не зависит от конфигурации display_errors
. Конфигурация php.ini по умолчанию регистрирует данные об ошибках до stderr
при запуске скриптов из командной строки. Под Apache они отображаются в /etc/httpd/logs/error_log
.
Проверьте php_error_cb
в main.c
источника PHP. В частности, строка 1056 дает понять, что любые сообщения формата "%%% s% s% s on line% d" связаны с конфигурацией регистрации ошибок (информация об ошибке из-за display_errors
не будет иметь "PHP:" prefix).
Ответ 2
Несколько возможных решений, отвечая, потому что раздел комментариев злился на меня.
Изменить №3 с помощью решения:
По-видимому, E_ERROR и display_errors не играют хорошо вместе
Вы можете установить error_reporting в E_ALL и ~ E_ERROR, а просто позволить обработчику выключения обрабатывать фатальное (так как это последнее, что нужно назвать так или иначе).
Кроме того, E_ALL
не включает E_DEPRECATED
до PHP 5.4.0, поэтому, если вы тоже хотите его поймать, используйте ~0 & ~E_ERROR
display_errors могут быть прослушиваемы
Вот суть в том, как вы можете заставить его выплюнуть ошибки, даже если вы сказали это не:
https://gist.github.com/1483028
Если вы установите display_errors на 0 через ini_set(), он все равно отобразит Fatal Errors
Хотя display_errors можно установить во время выполнения (с помощью ini_set()), это не повлияет, если script имеет фатальные ошибки. Это связано с тем, что желаемое действие во время выполнения не выполняется.
Кроме того, вы можете отправить его также в stderr, так что это потрясающе.
http://www.php.net/manual/en/errorfunc.configuration.php#ini.display-errors
Изменить 2:
Убедитесь, что вы изменили правильный php.ini
Просто подумал об этом и прокомментировал как таковой, но есть более одного файла php.ini. Если вы делаете это в командной строке, вам нужно отредактировать cli one (/etc/php5/cli/php.ini на Ubuntu), а не веб-сайт (/etc/php5/apache2/php. INI)
Думаю, вам просто нужно установить php.ini для отображения display_errors 0.