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