Перейти к содержимому

Ошибка после обновления PHP - причины по убыванию частоты

Сайт перестал открываться после смены версии PHP: белый экран, ошибка 500 или отвалилась часть страниц.

Как проверить

Смотрим, что именно упало, в логе PHP:

Окно терминала
tail -n 60 /var/log/php-fpm/error.log 2>/dev/null
grep -iE 'fatal|uncaught|deprecated' /var/log/nginx/error.log | tail -20

Белый экран - это фатальная ошибка при выключенном выводе. Текст её всегда в логе, и в нём есть файл со строкой. Если файл лежит в /local/ или в шаблоне сайта, дело в своём коде, а не в платформе.

Сверяем версию PHP с требованиями платформы:

Окно терминала
php -v
php -m | tr '\n' ' ' # список подключённых расширений
php -i | grep -E '^(extension_dir|Loaded Configuration)' # откуда они берутся

Обновление интерпретатора часто теряет расширения: пакеты ставятся под конкретную версию, и после перехода их надо ставить заново. Отсутствие mbstring или json роняет сайт целиком.

Причины

  1. Свой код не пережил смену версии примерно 40% случаев

    ПризнакПадают отдельные страницы, в логе файл из /local/ или из шаблона сайта.

    ПроверкаЧитаем лог: имя файла и строка называют место точно.

    Что делатьПравим свой код под новую версию: обновление платформы приводит к совместимому виду только ядро.

  2. После обновления отвалились расширения PHP примерно 30% случаев

    ПризнакСайт не открывается целиком, в логе жалоба на неизвестную функцию из расширения.

    ПроверкаСравниваем список подключённых расширений с тем, что было до обновления.

    Что делатьСтавим недостающие пакеты под новую версию и перезапускаем обработчик PHP.

  3. Платформа старее, чем поддерживает новый PHP примерно 20% случаев

    ПризнакОшибки идут из файлов ядра, а не из своего кода.

    ПроверкаСмотрим версию продукта и требования этой версии к интерпретатору.

    Что делатьВозвращаем прежний PHP, обновляем платформу и только после этого повторяем переход.

  4. Разошлась кодировка соединения с базой примерно 10% случаев

    ПризнакСайт работает, но русский текст выводится знаками вопроса.

    ПроверкаСверяем кодировку соединения в настройках подключения с кодировкой таблиц.

    Что делатьПриводим параметры подключения к кодировке базы: клиент новой версии выбирает её иначе.

Если ничего не помогло

Включаем вывод ошибок на копии сайта, а не на боевом:

// /bitrix/.settings.php, только на копии
'exception_handling' => ['value' => [
'debug' => true,
'handled_errors_types' => E_ALL & ~E_DEPRECATED,
]],

С включённым выводом фатальная ошибка показывается прямо на странице вместе со стеком вызовов. На боевом это открывает пути и имена файлов посторонним, поэтому проверку делают на копии.

Возвращаемся на прежнюю версию, если правка затягивается:

Окно терминала
# в окружении версия выбирается пакетами: откат вернёт сайт в рабочее состояние
yum install php74-php-fpm php74-php-mbstring php74-php-mysqlnd
systemctl restart php-fpm nginx

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

Ищем в своём коде вызовы, удалённые в новой версии:

Окно терминала
# самые частые пропажи: each, create_function, mysql_*, неявные приведения
grep -rnE '\b(each|create_function|mysql_(connect|query|fetch))\s*\(' \
/home/bitrix/www/local /home/bitrix/www/bitrix/templates 2>/dev/null | head -30

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

Сверяем кодировку соединения с кодировкой таблиц:

SHOW VARIABLES LIKE 'character_set_client';
SELECT TABLE_NAME, TABLE_COLLATION FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'sitemanager' LIMIT 5;

Расхождение и даёт знаки вопроса вместо русского текста: сайт работает, а данные приходят разобранными не в той кодировке.

Частые вопросы

Почему сайт работает только на старой версии PHP?

В коде проекта остались вызовы, удалённые в новой версии. Ядро платформы обновление приводит к совместимому виду, а /local/, шаблоны и сторонние модули - нет: их правят руками.

Ошибка json_failure после обновления - что это?

Обычно потерянное расширение работы с JSON либо несовпадение кодировки: функция получает строку, которую не может разобрать. Проверяют список расширений и кодировку соединения с базой.

Восстановление из копии падает на новом PHP.

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

Обновлять PHP или сначала платформу?

Сначала платформу. Свежая версия продукта работает и на старом интерпретаторе, а старая на новом - нет, и обратный порядок оставляет сайт нерабочим.

Смежное

Первоисточник