Де шукати логи PHP: error_log і шлях до файлу
PHP записує повідомлення про помилки туди, куди вказує директива error_log у php.ini або в конфігу пулу PHP-FPM. Дізнатися точний шлях можна без редагування файлів — команда php -i покаже реальне значення, яке використовує інтерпретатор просто зараз.
php -i | grep error_log
Для сайтів на Nginx і PHP-FPM типовий шлях — /var/log/php8.3-fpm.log для помилок самого пулу і окремий error_log усередині блоку pool для помилок конкретного сайту. Якщо директива error_log не задана явно, PHP-FPM пише в загальний системний журнал, і знайти там помилку одного сайту серед сотень чужих рядків важко.
display_errors і log_errors: різні завдання
display_errors виводить текст помилки прямо в HTML-сторінку, log_errors записує її у файл. На продакшені ці директиви повинні працювати в протилежних режимах.
display_errors = Off
log_errors = On
error_log = /var/log/php/app-error.log
Показ помилок у браузері — це витік інформації про шляхи, версії бібліотек і структуру бази даних, що напряму стосується теми статті про безпеку PHP через налаштування php.ini. Журналювання у файл, навпаки, повинне бути увімкнене завжди, навіть на проді.
Розбір типового фатала: Allowed memory size exhausted
Рядок із журналу виглядає так: PHP Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 20480 bytes) in /var/www/app/import.php on line 84. Число 134217728 байтів — це 128 мегабайтів, значення memory_limit. Рядок каже, що скрипту не вистачило пам'яті саме в момент спроби виділити ще 20 кілобайтів, а не загалом.
Перший крок — не піднімати memory_limit наосліп, а відкрити файл на вказаному рядку і зрозуміти, що там відбувається: найчастіше це завантаження всього результату запиту в масив або обробка файлу цілком замість читання частинами. Якщо скрипт запускається з cron, різниця в лімітах між CLI і FPM розібрана у статті про PHP у cron і відмінності CLI від FPM.
Рівні error_reporting: що означають константи
| Константа | Що ловить | Варто вмикати на проді |
|---|---|---|
| E_ERROR | Фатальні помилки, скрипт зупинено | так |
| E_WARNING | Некритичні помилки виконання | так, у журнал |
| E_DEPRECATED | Застарілі конструкції мови | так, у журнал |
| E_NOTICE | Звернення до неініціалізованої змінної | за бажанням |
| E_STRICT | Рекомендації щодо стилю коду | ні, зайвий шум |
Для продакшену типове значення — error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT), а вивід із цього набору завжди йде в error_log, а не на екран.
Часті записи в журналі і що вони означають
- PHP Parse error: syntax error, unexpected token — помилка в самому коді, скрипт не запустився взагалі, деплой зламано.
- PHP Fatal error: Uncaught Error: Call to a member function on null — звернення до методу об'єкта, який не було створено, найчастіше через невдалий запит до бази.
- PHP Warning: file_put_contents failed to open stream — бракує прав на запис у каталог або каталог не існує.
- PHP Deprecated: Implicit conversion from float to int loses precision — код доживає свій вік і потребує правок перед наступним оновленням PHP.
- PHP Fatal error: Maximum execution time exceeded — скрипт уперся в max_execution_time, а не в memory_limit, лікується інакше.
Підсумок: чек-лист налаштування журналювання PHP
- display_errors = Off і log_errors = On задані окремо для вебрежиму і для CLI.
- error_log вказує на конкретний файл сайту, а не на загальний системний журнал.
- Ротація файлу журналу налаштована через logrotate, щоб диск не заповнився за місяць.
- error_reporting вмикає E_ALL без E_DEPRECATED і E_STRICT на проді.
- Для кожного фатала з журналу є прив'язка до файлу і рядка, а не лише до тексту помилки.