☰
WORDPRESS / PRACTICE

Синхронизация OPcache после деплоя WordPress: как убрать старый PHP-код

Синхронизация OPcache после деплоя WordPress: как убрать старый PHP-код

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

Причина может быть не в кэше WordPress, Redis или CDN, а в OPcache — кэше скомпилированного PHP-кода. Если PHP-FPM использует несколько worker-процессов, у них может быть разное состояние кэша. Ниже рассмотрим практический порядок проверки и синхронизации OPcache после деплоя.

Что происходит с PHP-кодом после деплоя

Во время первого выполнения PHP-файла OPcache сохраняет его скомпилированную версию в памяти. Следующие запросы могут выполнять уже подготовленный байткод, не читая файл с диска и не компилируя его заново.

В соответствии с настройкой opcache.validate_timestamps PHP периодически проверяет, изменился ли файл на диске. Если проверка отключена, что часто делают в production ради предсказуемой производительности, OPcache не узнает о новом содержимом файла самостоятельно. Обновленный файл может начать использоваться только после очистки кэша или запуска новых PHP-FPM worker-процессов.

Ситуация усложняется, если PHP-FPM работает с несколькими процессами. Часть worker-процессов могла загрузить новый код, а часть — продолжать выполнять старый. Поэтому ошибка может возникать нестабильно: например, только для отдельных запросов или пользователей.

  • OPcache кэширует PHP-код, а не HTML-страницы WordPress.
  • wp cache flush очищает object cache, но не гарантирует очистку OPcache.
  • CLI и PHP-FPM могут использовать разные версии PHP и разные конфигурационные файлы.
  • После изменения кода надежнее всего синхронизировать состояние worker-процессов через reload или restart PHP-FPM.

Как распознать проблему с OPcache

Перед перезапуском сервисов проверьте логи веб-сервера, PHP-FPM и самого приложения. О рассинхронизации часто говорят ошибки, которые не соответствуют текущему коду на диске.

Особенно показательны сообщения об отсутствующем методе или классе после обновления плагина, старый путь к файлу в stack trace, несовместимость двух частей одного релиза или ошибки, исчезающие после повторного запроса. Если после полного перезапуска PHP-FPM проблема стабильно исчезает, OPcache или жизненный цикл worker-процессов являются одними из главных подозреваемых.

  • Сравните время изменения файлов на диске со временем деплоя.
  • Проверьте, доступны ли все файлы нового релиза пользователю, от имени которого работает PHP-FPM.
  • Уточните, воспроизводится ли ошибка на всех веб-узлах, если сайт работает за балансировщиком.
  • Не делайте вывод только по результату команды php -i: она может показывать конфигурацию CLI, а не FPM.

Проверка конфигурации CLI и FPM

Для CLI можно посмотреть активные параметры OPcache:

php --ini
php -i | grep -E 'opcache.(enable|validate_timestamps|revalidate_freq|reset|interned_strings_buffer)'

Graceful reload PHP-FPM после деплоя

Первый шаг после успешного деплоя — выполнить graceful reload PHP-FPM. Такой reload просит master-процесс постепенно завершить старые worker-процессы и создать новые. Новые worker-процессы загрузят актуальный код и сформируют собственное состояние OPcache.

Название сервиса зависит от дистрибутива и установленной версии PHP. Перед выполнением команды проверьте точное имя unit-файла в своей системе.

  • Для systemd часто используется команда вроде systemctl reload php8.2-fpm.
  • В другой системе имя может быть php-fpm, php8.1-fpm или другим.
  • После reload проверьте статус сервиса и журналы, чтобы убедиться, что новые worker-процессы действительно запустились.
sudo systemctl reload php8.2-fpm
sudo systemctl status php8.2-fpm --no-pager
sudo journalctl -u php8.2-fpm -n 100 --no-pager

Когда нужен полный restart

Если после graceful reload старый код все еще выполняется, выполните полный restart PHP-FPM. Он останавливает все worker-процессы и запускает их заново, поэтому старое состояние OPcache исчезает вместе с завершенными процессами.

Restart следует планировать с учетом нагрузки: во время короткого перезапуска активные PHP-запросы могут быть прерваны, а новые — временно попасть в очередь. В production сначала проверьте процедуру на staging или выполните ее в период низкой нагрузки.

  • Сначала соберите логи: перезапуск может скрыть симптом, но не устранить ошибку деплоя.
  • Убедитесь, что конфигурация PHP-FPM корректна, иначе после restart сервис может не запуститься.
  • После restart проверьте healthcheck, главную страницу, авторизацию и критически важные сценарии WordPress.
sudo systemctl restart php8.2-fpm
sudo systemctl status php8.2-fpm --no-pager

Atomic deploy, symlink и права доступа

Во время atomic deploy новый код обычно распаковывают в каталог релиза, после чего symlink current переключают на него. Такой подход снижает риск неполного обновления, но не отменяет требований к OPcache и доступу PHP-FPM.

Убедитесь, что PHP-FPM может пройти по всей цепочке каталогов к новому релизу и прочитать PHP-файлы. Даже корректные права на сам файл не помогут, если один из родительских каталогов недоступен пользователю или группе PHP-FPM.

Отдельное внимание уделите старым worker-процессам, которые могли сохранить код предыдущего релиза. После переключения symlink выполняйте reload, а для production-деплоев с отключенной проверкой timestamp рассматривайте это как обязательный этап.

  • Проверьте, куда указывает current после деплоя.
  • Проверьте права на каталоги релиза и возможность чтения файлов пользователем PHP-FPM.
  • Не удаляйте старый релиз сразу, если активные процессы еще могут иметь открытые файлы.
  • Все веб-серверы и PHP-FPM-инстансы за балансировщиком должны получить одинаковый релиз и reload.
readlink -f /var/www/site/current
namei -l /var/www/site/current/wp-content/plugins/example/plugin.php
sudo -u www-data test -r /var/www/site/current/wp-load.php && echo OK

Как построить надежный порядок деплоя

Синхронизация OPcache должна быть частью процесса деплоя, а не ручным исправлением после жалобы пользователя. Это особенно важно, если opcache.validate_timestamps отключен.

Типичный порядок можно адаптировать под вашу инфраструктуру: сначала подготовить новый релиз, проверить его файлы и конфигурацию, переключить symlink, выполнить graceful reload, а затем запустить smoke-тесты. Если состояние не выровнялось, соберите логи и выполните restart.

  • Не смешивайте деплой файлов с непроверенными изменениями базы данных без плана обеспечения совместимости.
  • Добавьте проверку HTTP-ответа и ключевых страниц после reload.
  • Для диагностики фиксируйте идентификатор релиза в ответах или логах, чтобы видеть, какой код обработал запрос.
  • Используйте одинаковую политику reload на всех PHP-FPM-узлах.
  • Не очищайте OPcache через случайные веб-скрипты на production: это создает риски доступа и неконтролируемого сброса кэша.
deploy_release
switch_current_symlink
sudo systemctl reload php8.2-fpm
run_smoke_tests
# если старый код сохраняется:
sudo systemctl restart php8.2-fpm

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

Поможет ли wp cache flush обновить PHP-код?

Нет. wp cache flush работает с object cache WordPress, например Redis или Memcached, но не управляет OPcache PHP-FPM. Для обновления скомпилированного PHP-кода требуется reload или restart PHP-FPM — в зависимости от ситуации.

Почему CLI показывает одну конфигурацию OPcache, а сайт работает иначе?

CLI и PHP-FPM могут использовать разные версии PHP, php.ini и дополнительные ini-файлы. Проверяйте параметры именно в контексте FPM через журналы, контрольную диагностику или безопасный внутренний healthcheck, а не только с помощью команды php -i.

Нужно ли всегда выполнять полный restart после каждого деплоя?

Не обязательно. Во многих конфигурациях достаточно graceful reload, который создает новые worker-процессы. Полный restart нужен, если старый код сохраняется, worker-процессы не обновились или есть другая причина, из-за которой reload не выровнял состояние.

Безопасно ли отключать opcache.validate_timestamps?

Для production это возможно, но тогда процесс деплоя должен явно предусматривать reload или restart PHP-FPM. Без этого PHP может продолжать выполнять старый код после изменения файлов.

Вывод

Если WordPress после деплоя выполняет старую версию PHP-файлов, проверяйте не только кэш WordPress, но и OPcache каждого PHP-FPM worker-процесса. Начните с логов, проверьте различия между CLI и FPM, права доступа и symlink текущего релиза.

Практическое правило простое: после переключения релиза выполните graceful reload PHP-FPM, проверьте сайт и логи, а при сохранении симптомов сделайте полный restart. Этот шаг стоит автоматизировать в CI/CD, особенно если проверка timestamp для OPcache отключена.

← Все материалы WordPress