После обновления плагина, темы или самого 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 отключена.