Fatal error на production: как искать причину без вывода ошибок

Fatal error на production часто выглядит как белый экран, 500 ошибка или пустой ответ. Пользователь видит проблему, но разработчику нельзя просто включить display_errors и показать трассировку всему интернету. Диагностика должна идти через логи и безопасные временные инструменты.

Главная задача — найти точную ошибку и файл, не раскрывая внутренности проекта пользователям.

Не включать display_errors на production

Показ ошибок в браузере может раскрыть пути на сервере, структуру проекта, SQL, имена классов, токены и другие технические детали. На production ошибки должны писаться в лог.

display_errors = Off
log_errors = On
error_reporting = E_ALL

После изменения php.ini нужно перезапустить PHP-FPM или соответствующий сервис.

sudo systemctl restart php8.2-fpm

Проверить PHP error log

Первое место для поиска fatal error — PHP error log. Путь зависит от сервера и PHP-FPM pool.

tail -n 150 /var/log/php-fpm/error.log
tail -n 150 /var/log/php8.2-fpm.log
tail -n 150 /var/log/php/error.log

Если путь неизвестен, его можно искать в конфигурации:

php -i | grep error_log
grep -R "php_admin_value\[error_log\]" /etc/php/*/fpm/pool.d/

Проверить nginx или Apache

Если запрос не дошёл до PHP, PHP-лог может быть пустым. Тогда нужно смотреть веб-сервер.

tail -n 150 /var/log/nginx/error.log
tail -n 150 /var/log/nginx/access.log

В access.log полезно найти конкретный проблемный URL и код ответа.

grep "/problem-page/" /var/log/nginx/access.log | tail

Последние изменения

Fatal error часто появляется после деплоя, обновления Composer, изменения PHP-версии или ручной правки файла. Нужно быстро понять, что менялось.

git log --oneline -5
git diff HEAD~1..HEAD
find . -name "*.php" -mtime -1 -print

Если проект без git, задача сложнее. Тогда особенно важны бэкапы и журнал изменений.

Проверить синтаксис PHP-файлов

Если есть подозрение на синтаксическую ошибку, можно проверить изменённые файлы через php -l.

php -l path/to/file.php

Для проекта целиком:

find local app modules -name "*.php" -print0 | xargs -0 -n1 php -l

Команду нужно адаптировать под структуру проекта, чтобы не проверять vendor без необходимости.

OPcache

Иногда код уже исправили, но сервер продолжает выполнять старую версию из OPcache. Особенно если validate_timestamps отключён или настроен большой revalidate_freq.

php -i | grep opcache.validate_timestamps
php -i | grep opcache.revalidate_freq

Для быстрой проверки можно перезапустить PHP-FPM.

sudo systemctl restart php8.2-fpm

Shutdown handler

Если в проекте трудно поймать fatal error, можно временно добавить shutdown handler, который пишет последнюю ошибку в отдельный лог.

register_shutdown_function(function () {
    $error = error_get_last();

    if ($error !== null) {
        error_log(json_encode([
            'type' => $error['type'],
            'message' => $error['message'],
            'file' => $error['file'],
            'line' => $error['line'],
        ], JSON_UNESCAPED_UNICODE));
    }
});

Такой код нужно использовать аккуратно и не превращать в постоянный шумный лог.

Права на логи

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

ls -la runtime/logs
ls -la var/log
touch runtime/logs/test.log

Чек-лист

  1. Не включать display_errors для пользователей.
  2. Проверить PHP error log.
  3. Проверить nginx или Apache error log.
  4. Найти проблемный URL в access.log.
  5. Проверить последние изменения кода.
  6. Проверить синтаксис изменённых PHP-файлов.
  7. Проверить Composer и autoload, если менялись зависимости.
  8. Проверить OPcache после исправления.
  9. Проверить права на директории логов.

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

Комментарии (0)

Пока нет комментариев. Будьте первым!