Біла сторінка смерті WordPress (WSOD): 12 перевірок, які справді працюють

Було корисно?

Біла сторінка смерті — це спосіб WordPress повідомити, що «щось вибухнуло», при цьому відмовляючись сказати, де впали уламки. Користувачі бачать порожню сторінку. Ваш моніторинг показує «200 OK». Ваш на-колі мозок бачить власну кінцівку.

Це посібник, який я хотів би, щоб більше команд виконували: швидка тріажна діагностика спочатку, потім дисципліновані перевірки, що перетворюють таємницю на одну кореневу причину, яку можна виправити і запобігти.

Швидкий план діагностики (перші 10 хвилин)

Швидкість важлива, але гадання повільніше, ніж прочитати правильний лог один раз. Мета — знайти вузьке місце: відбувається помилка до запуску PHP, всередині PHP чи після PHP (база даних/кеш/запис на диск)?

Хвилини 0–2: підтвердіть, що означає «білий»

  • Перевірте HTTP-статус і заголовки. 500 з порожнім тілом відрізняється від 200, що повертає пробіли.
  • Порівняйте головну сторінку та wp-admin. Якщо wp-admin завантажується, часто проблема в темі/плагіні фронтенду, а не в глобальному рантаймі.
  • Обійдіть CDN і кеші. Якщо origin в порядку, а крайова мережа віддає пустоту, ви діагностуєте не ту систему.

Хвилини 2–5: читайте журнали як дорослий

  • Журнал помилок веб‑сервера (Nginx/Apache) для помилок upstream і таймаутів.
  • Логи PHP-FPM / PHP для фаталів, вичерпання пам’яті, проблем з OPcache.
  • Фатал на рівні додатка через WordPress debug log, якщо ви можете увімкнути його безпечно.

Хвилини 5–10: ізолюйте плагіни/теми без зміни коду

  • Вимкніть усі плагіни (WP-CLI або перейменування папки) і протестуйте знову.
  • Переключіться на відому стабільну тему за замовчуванням.
  • Якщо все ще біло, перестаньте звинувачувати «плагін» і дивіться на невідповідність версій PHP, відсутні розширення, підключення до БД, диск і пам’ять.

Корисна ментальна модель: WSOD рідко означає «WordPress упав». Зазвичай це «PHP спіймав фатал і буферизація виводу дала нічого» або «рантайм не може читати/записувати потрібні файли і падає посеред запиту».

Кілька фактів (та невелика історія) про WSOD

  • WSOD існував до WordPress. Термін був популяризований у PHP-екосистемі, коли фатали приховувалися в продакшні, залишаючи порожній вивід.
  • WordPress раніше за замовчуванням падав мовчки. Ранні конфігурації часто мали display_errors вимкненим без централізованого логування, через що WSOD був фактично нормою.
  • «Режим відновлення» відносно новий. WordPress додав захист/режим відновлення при фатальних помилках (епоха 5.2), який може надсилати листи адміністраторам і дозволяти відключати зламані плагіни/теми. Це допомагає, але не всесильно.
  • WSOD може супроводжуватись 200 OK. Багато збоїв відбуваються після відправки заголовків або обробляються так, що повертається порожнє тіло з успішним статусом — тому перевірки доступності брешуть.
  • OPcache зробив WSOD і кращим, і гіршим. Він покращує продуктивність, але застарілий байткод після деплою може продовжувати виконувати старий код навіть якщо файли змінені.
  • Сучасний PHP суворіший. Оновлення версій PHP можуть перетворювати «попередження, які ігнорували роками» на фатали через видалені функції або жорсткішу типізацію.
  • Вичерпання пам’яті все ще — одна з головних причин. Особливо з конструкторами сторінок, великими інсталяціями WooCommerce і «допоміжними» плагінами без оптимізації, що роблять важку роботу на кожному запиті.
  • Несправності з диском часто маскуються під WSOD. Повний диск, файловий простір тільки для читання або повільний NFS можуть призвести до того, що PHP-сесії/завантаження/кеші не записуються і сторінки падають у пустоту.
  • CDN може кешувати порожнечу. Якщо origin коротко повернув порожній 200, крайова мережа з радістю роздасть цю порожнечу всім до закінчення TTL.

Цитата, яку підтверджує кожен інцидент WSOD: Все ламається, постійно. — Werner Vogels

12 перевірок, які справді працюють (з командами, виводом, рішеннями)

Кожна перевірка нижче — реальне завдання: команда, яку можна виконати, що означає вивід і яке рішення прийняти. Виконуйте ці кроки в порядку, якщо лише у вас немає очевидного «димлячого пістолета».

Жарт №1: WSOD схожий на нараду без порядку денного: всі присутні, нічого не відбувається, і якось ви все одно втрачаєте гроші.

Перевірка 1) Підтвердіть режим помилки за допомогою curl (статус, заголовки, розмір тіла)

cr0x@server:~$ curl -sS -D- -o /tmp/body.html -w "\nstatus=%{http_code} size=%{size_download} time=%{time_total}\n" https://example.com/ | head -n 20
HTTP/2 200
date: Thu, 26 Dec 2025 14:21:09 GMT
content-type: text/html; charset=UTF-8
cache-control: max-age=0, must-revalidate
server: nginx

status=200 size=0 time=0.312

Що це означає: 200 з size=0 — класична поведінка WSOD: запит успішний на HTTP-рівні, але тіло не згенеровано (або обрізано).

Рішення: Розглядайте це як помилку на рівні додатка/рантайму, а не як «веб‑сервер впав». Перейдіть до логів і PHP-FPM.

Перевірка 2) Обійдіть CDN / крайовий кеш, щоб перевірити поведінку origin

cr0x@server:~$ curl -sS -H "Cache-Control: no-cache" -H "Pragma: no-cache" -D- -o /dev/null https://example.com/
HTTP/2 200
date: Thu, 26 Dec 2025 14:21:31 GMT
content-type: text/html; charset=UTF-8
cf-cache-status: HIT
server: cloudflare

Що це означає: Крайова мережа віддає кешований контент (можливо кешовану порожнечу). Ваш «no-cache» запит не примусив звернутися до origin.

Рішення: Тестуйте безпосередньо origin, звертаючись на IP/з правильним Host header або на внутрішню адресу LB. Якщо origin в порядку — очистіть кеш на краю; якщо origin зламаний — припиніть шукати проблему в CDN.

Перевірка 3) Спочатку подивіться журнал помилок веб‑сервера (приклад Nginx)

cr0x@server:~$ sudo tail -n 80 /var/log/nginx/error.log
2025/12/26 14:20:58 [error] 23144#23144: *9181 FastCGI sent in stderr: "PHP message: PHP Fatal error:  Uncaught Error: Call to undefined function mysql_connect() in /var/www/html/wp-content/plugins/legacy-db/legacy.php:41" while reading response header from upstream, client: 203.0.113.10, server: example.com, request: "GET / HTTP/2.0", upstream: "fastcgi://unix:/run/php/php8.2-fpm.sock:", host: "example.com"

Що це означає: Це золото: фатальна помилка всередині плагіна, що викликає видалену функцію. PHP ніколи не створив валідну відповідь.

Рішення: Негайно вимкніть цей плагін. Потім заплануйте виправлення коду або заміну. Також з’ясуйте, чому це потрапило в продакшн (про це далі).

Перевірка 4) Перевірте стан сервісу PHP-FPM і недавні падіння

cr0x@server:~$ sudo systemctl status php8.2-fpm --no-pager
● php8.2-fpm.service - The PHP 8.2 FastCGI Process Manager
     Loaded: loaded (/lib/systemd/system/php8.2-fpm.service; enabled)
     Active: active (running) since Thu 2025-12-26 14:00:01 UTC; 21min ago
   Main PID: 1109 (php-fpm8.2)
      Tasks: 19 (limit: 18962)
     Memory: 214.5M
        CPU: 1min 42.110s
     CGroup: /system.slice/php8.2-fpm.service
             ├─1109 "php-fpm: master process (/etc/php/8.2/fpm/php-fpm.conf)"
             └─1132 "php-fpm: pool www"

Що це означає: PHP-FPM запущено. Це не означає, що він здоровий; просто він живе. Потрібно перевіряти логи на предмет аварій воркерів, max_children, повільних запитів.

Рішення: Якщо PHP-FPM впав або флапає — виправте це спочатку (конфігурація, пам’ять, сегментаційні відмови, пакунки). Якщо він працює — переходьте до логів.

Перевірка 5) Прочитайте лог PHP-FPM на предмет фаталів (пам’ять, таймаути, сегфолти)

cr0x@server:~$ sudo tail -n 120 /var/log/php8.2-fpm.log
[26-Dec-2025 14:20:58] WARNING: [pool www] child 1733 said into stderr: "PHP Fatal error:  Allowed memory size of 268435456 bytes exhausted (tried to allocate 4096 bytes) in /var/www/html/wp-includes/class-wpdb.php on line 2345"
[26-Dec-2025 14:21:03] WARNING: [pool www] child 1735 exited on signal 11 (SIGSEGV) after 2.412340 seconds from start
[26-Dec-2025 14:21:03] NOTICE: [pool www] child 1741 started

Що це означає: Можуть співіснувати дві проблеми: вичерпання пам’яті (зазвичай детерміністичне для запиту) і сегфолти (часто баг в розширенні, OPcache або пошкодження пам’яті). Обидві можуть давати WSOD.

Рішення: Для вичерпання пам’яті: ідентифікуйте запит/плагін/тему, що спричиняє проблему; підвищувати ліміти лише після розуміння причини. Для сегфолтів: перевірте розширення (Redis, Imagick), OPcache, версію PHP; розгляньте відкат або вимкнення розширення.

Перевірка 6) Увімкніть логування WordPress безпечним способом (не display_errors)

У продакшні потрібні логи, а не публічний вивід помилок. Змініть wp-config.php, щоб логувати у файл. Потім відтворіть запит один раз.

cr0x@server:~$ sudo -u www-data sed -n '1,120p' /var/www/html/wp-config.php | tail -n 20
define('WP_DEBUG', false);
define('WP_DEBUG_LOG', false);
define('WP_DEBUG_DISPLAY', false);

Тимчасово змініть на:

cr0x@server:~$ sudo -u www-data perl -0777 -pe 's/define\(\x27WP_DEBUG\x27,\s*false\);/define(\x27WP_DEBUG\x27, true);/; s/define\(\x27WP_DEBUG_LOG\x27,\s*false\);/define(\x27WP_DEBUG_LOG\x27, true);/; s/define\(\x27WP_DEBUG_DISPLAY\x27,\s*false\);/define(\x27WP_DEBUG_DISPLAY\x27, false);/' -i /var/www/html/wp-config.php

Потім відвідайте сайт і прочитайте:

cr0x@server:~$ sudo tail -n 80 /var/www/html/wp-content/debug.log
[26-Dec-2025 14:22:15 UTC] PHP Fatal error:  Uncaught TypeError: strpos(): Argument #1 ($haystack) must be of type string, null given in /var/www/html/wp-content/themes/custom/functions.php:912
Stack trace:
#0 /var/www/html/wp-content/themes/custom/functions.php(912): strpos()
#1 /var/www/html/wp-includes/class-wp-hook.php(324): theme_filter()

Що це означає: Код теми падає. Це може затемнити фронтенд, тоді як wp-admin усе ще працює.

Рішення: Переключіть тему зараз; виправляйте тему після відновлення сервісу. Поверніть налаштування логування після того, як збережете стек‑трек (або залиште логування, але налаштуйте ротацію).

Перевірка 7) Вимкніть всі плагіни через WP-CLI (швидко, відновлювано)

cr0x@server:~$ cd /var/www/html
cr0x@server:~$ sudo -u www-data wp plugin list --status=active
+---------------------+--------+-----------+---------+
| name                | status | update    | version |
+---------------------+--------+-----------+---------+
| redis-cache         | active | none      | 2.5.2   |
| legacy-db           | active | available | 1.3.1   |
| woo-commerce        | active | none      | 8.5.0   |
+---------------------+--------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp plugin deactivate --all
Plugin 'redis-cache' deactivated.
Plugin 'legacy-db' deactivated.
Plugin 'woo-commerce' deactivated.
Success: Deactivated 3 of 3 plugins.

Що це означає: Ви прибрали найбільшу змінну: код плагінів. Якщо WSOD зник — вмикайте плагіни по одному (бінарний пошук при багатьох).

Рішення: Якщо вимкнення плагінів вирішує проблему: вмикайте по одному, поки не з’явиться помилка; потім патчуйте чи замініть винуватця. Якщо не допомагає: дивіться тему/рантайм/БД/зберігання.

Перевірка 8) Переключіться на тему за замовчуванням без UI адмінки

Якщо фронтенд впав, а ви не можете зайти в wp-admin, переключення теми через CLI — чисте рішення.

cr0x@server:~$ sudo -u www-data wp theme list
+----------------+----------+-----------+---------+
| name           | status   | update    | version |
+----------------+----------+-----------+---------+
| twentytwentyfour | inactive | none      | 1.2     |
| custom         | active   | none      | 3.8     |
+----------------+----------+-----------+---------+
cr0x@server:~$ sudo -u www-data wp theme activate twentytwentyfour
Success: Switched to 'Twenty Twenty-Four' theme.

Що це означає: Ви замінили шлях виконання, що рендерить більшість сторінок. WSOD часто живе в functions.php або в «утилітному» файлі теми.

Рішення: Якщо це відновить сайт — залиште тему за замовчуванням активною, поки виправляєте кастомну тему. Команда брендингу виживе.

Перевірка 9) Перевірте версію PHP, завантажені модулі та відсутні розширення

cr0x@server:~$ php -v
PHP 8.2.12 (cli) (built: Nov  8 2025 10:12:34) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.12, Copyright (c) Zend Technologies
    with Zend OPcache v8.2.12, Copyright (c), by Zend Technologies
cr0x@server:~$ php -m | egrep -i 'mysqli|pdo_mysql|imagick|redis|opcache'
mysqli
PDO
pdo_mysql
redis
Zend OPcache

Що це означає: Базові розширення присутні. Якщо відсутні mysqli або pdo_mysql, WordPress може серйозно падати. Якщо відсутній imagick, деякий код плагінів/тем може викликати фатал, припускаючи його існування.

Рішення: Якщо потрібно розширення — встановіть його або змініть плагін/тему, яка на нього покладається. Також переконайтеся, що версії PHP-FPM і CLI збігаються; невідповідності створюють «працює в CLI, ламається на вебі» проблеми.

Перевірка 10) Підтвердіть ліміти пам’яті на рівні PHP і WordPress

cr0x@server:~$ php -r 'echo "memory_limit=".ini_get("memory_limit").PHP_EOL;'
memory_limit=256M
cr0x@server:~$ grep -R "WP_MEMORY_LIMIT" -n /var/www/html/wp-config.php
42:define('WP_MEMORY_LIMIT', '128M');
43:define('WP_MAX_MEMORY_LIMIT', '256M');

Що це означає: WordPress може обмежувати пам’ять нижче за глобальну настройку PHP. Адмінські запити використовують WP_MAX_MEMORY_LIMIT; фронтенд — WP_MEMORY_LIMIT. WSOD, що торкається лише wp-admin, може бути зворотнім варіантом.

Рішення: Якщо ви отримуєте memory fatals — тимчасово підніміть WP_MEMORY_LIMIT, щоб співпав з PHP, але це не остаточне вирішення. Знайдіть важкий запит, нескінченний цикл або плагін, що робить необмежену роботу. Збільшення пам’яті — пластир, а не лікування.

Перевірка 11) Підтвердіть підключення до бази даних і перевірте «занадто багато підключень»

WordPress може показувати порожній екран, коли виклики до БД падають посеред рендерингу, особливо якщо помилки приглушуються і тема не обробляє null-значення.

cr0x@server:~$ mysql -h 127.0.0.1 -u wpuser -p -e "SELECT 1;"
Enter password:
1
1
cr0x@server:~$ mysql -h 127.0.0.1 -u root -p -e "SHOW STATUS LIKE 'Threads_connected'; SHOW VARIABLES LIKE 'max_connections';"
Enter password:
Threads_connected	148
max_connections	150

Що це означає: Ви близькі до максимальної кількості підключень. Коли сайт спалахує, воркери PHP стоять у черзі, а БД відмовляє у підключенні. Залежно від обробки помилок, це може проявлятися як WSOD.

Рішення: Короткостроково: зменшіть конкурентність (PHP-FPM pm.max_children) або підвищте max_connections у БД, якщо хост має ресурси. Довгостроково: оптимізуйте запити, додайте кешування правильно і припиніть запускати «повільну аналітику» в запиті.

Перевірка 12) Санітарія зберігання: диск повний, inode, права та монтовані readonly

Проблеми з диском — тихі вбивці PHP-застосунків: сесії не записуються, кеш не оновлюється, завантаження ламаються, а кодові шляхи поводяться дивно, коли файлові операції повертають false.

cr0x@server:~$ df -h /var/www /tmp
Filesystem      Size  Used Avail Use% Mounted on
/dev/vda1        40G   39G  160M 100% /
tmpfs           1.0G  1.0G     0 100% /tmp
cr0x@server:~$ df -i /
Filesystem     Inodes IUsed  IFree IUse% Mounted on
/dev/vda1     262144 262144     0  100% /
cr0x@server:~$ mount | grep ' on / '
/dev/vda1 on / type ext4 (ro,relatime,errors=remount-ro)

Що це означає: Трійний удар: диск повний, inode вичерпані, та файлову систему перемонтовано як тільки для читання. WordPress не зможе коректно обробити це; критичні файли не записуються і це може проявлятися як WSOD.

Рішення: Відновіть можливість запису і звільніть місце першочергово. Видаліть логи, очистіть тимчасові директорії, налаштуйте ротацію і дослідіть, чому система перемонтувалася в readonly (помилки диска, проблеми ядра). Не марнуйте час на перевстановлення плагінів, поки диск горить.

Бонус‑перевірка) OPcache: коли деплой «успішний», але код не змінюється

Це настільки поширено у продакшні, що заслуговує місця хоча б як бонус. Якщо тільки дванадцять перевірок — замініть ту, яку робите найрідше.

cr0x@server:~$ php -r 'echo "opcache.enable=".ini_get("opcache.enable").PHP_EOL; echo "opcache.validate_timestamps=".ini_get("opcache.validate_timestamps").PHP_EOL; echo "opcache.revalidate_freq=".ini_get("opcache.revalidate_freq").PHP_EOL;'
opcache.enable=1
opcache.validate_timestamps=0
opcache.revalidate_freq=2

Що це означає: При вимкненій перевірці часових міток PHP може ніколи не помітити зміни коду до перезапуску FPM. Це може тримати у виконанні зламану версію, навіть після того, як ви «виправили» файли.

Рішення: В моделях іммутабельного деплою це може бути прийнятно, якщо ви перезапускаєте PHP-FPM при деплої. Якщо ні — увімкніть валідацію чи додайте крок явного перезавантаження. Операційна послідовність важливіша за хитромудрість.

Жарт №2: «На моєму ноуті працює» — мило. Продакшн не мило.

Три корпоративні міні-історії з поля бою

Міні-історія 1: Інцидент через хибне припущення (оновлення PHP «має бути безпечно»)

Середня компанія запускала контентний WordPress за Nginx з реверс-проксі. Також у них була окрема ферма маркетингових мікросайтів. У вівторок вони оновили базовий образ для всіх PHP-сервісів з PHP 7.4 до PHP 8.2. Це було заплановано, погоджено і «протестовано».

Хибне припущення було простим: якщо сторінка на staging відкривається, production теж відкриється. Їхнє staging оточення мало інший набір плагінів — через ліцензування. Легасі-плагін, що обробляв стару інтеграцію БД, не був встановлений на staging, і ніхто не помітив, бо «це не мало значення». Але воно мало.

На production головна сторінка почала повертати порожній 200. Моніторинг залишався зеленим, бо health check хтів /robots.txt, який був статичним. Появилися тікети підтримки. На колі інженер побачив 200 і спочатку звинуватив CDN. Десять хвилин було втрачено на очищення кешів і редеплоях.

Виправлення було швидким, коли вони переглянули помилки Nginx: фатал від видаленої функції. Вони вимкнули плагін через WP-CLI, відновили сервіс і згодом замінили його на підтримувану інтеграцію.

Запобігання було менш привабливим: політика «паритету staging» тепер вимагала однаковий список плагінів (навіть якщо налаштовані по-різному), а оновлення потребували синтетичної транзакції, що зачіпала динамічні WordPress endpoint-и, а не тільки статичні файли.

Міні-історія 2: Оптимізація, що обернулась проти команди (object cache без запобіжників)

Команда Enterprise мала сайт WordPress, що стрибав у навантаженні під час пресрелізів. Хтось запропонував Redis object caching, щоб зменшити навантаження на БД. Гарна ідея. Вони швидко розгорнули, пораділи зменшенню CPU БД і перейшли до наступної задачі.

Через тижні оновлення плагіна внесло тонкий баг: він закешував великий PHP-об’єкт під ключем, що варіювався по user-agent і деяких query-параметрах. Ключі кешу вибухнули в кількості. Пам’ять Redis заповнилася, евікшн став агресивним, і затримки зросли. Під навантаженням запити PHP почали таймаутитися в очікуванні відповідей Redis.

Ззовні сайт виглядав як WSOD: сторінки були порожні або наполовину відрендерені. Внутрішні логи Nginx показували таймаути upstream. PHP-FPM мав багато активних воркерів у зависанні. База даних була в порядку, що вводило команду в оману, бо «ми вирішили БД проблему». Насправді вузьке місце перемістилося на інший сервер.

Відкат полягав у негайному вимкненні object caching (перейменувати drop-in файл), а потім обережному поверненні його з обмеженнями: адекватний TTL, обмеження пам’яті, дисципліна ключів і правило, що баги кешу — це продакшн‑аварія, а не «проблема продуктивності».

Урок: кешування — гострий інструмент. Якщо його розмахувати в переповненій кімнаті, хтось постраждає.

Міні-історія 3: Нудна, але правильна практика, що врятувала день (логи, ротація та канарка)

Фінансова команда вела WordPress як базу знань. Нічого екстравагантного, багато комплаєнсу. Їхні практики були неяскраві: централізовані логи, жорстка ротація, чеклист деплою і канарковий хост, який отримував трафік від внутрішніх користувачів першим.

Одного дня оновлення теми внесло фатал у рідко використовуваний шаблон сторінки. Канарка негайно почала логувати фатал. Оскільки логи були централізовані, на колі не потрібно було робити SSH‑героїзм; вони побачили точний стек‑трек у дашборді й відкотили пакет теми.

Зовнішні користувачі ніколи не бачили WSOD. Зміна була відвернута до публічного розгортання. Ні драми, ні воєнної кімнати, ні «можливо це DNS».

Це та частина, яку люди ненавидять: правильне рішення не було хитрою командою. Це була нудна процедура і спостережливість. Нудне — це фіча, коли ви відповідаєте за uptime.

Поширені помилки: симптом → корінь → виправлення

1) Порожня сторінка тільки на головній

  • Симптом: / біла; /wp-admin працює.
  • Корінь: Помилка в шаблоні теми, плагін, що підключається лише на фронтенді, або фатал у шорткоді, використаному на головній.
  • Виправлення: Переключіть тему через WP-CLI; вимкніть фронтенд‑плагіни; перевірте debug log на стек‑трек; поступово поверніть зміни.

2) Біла сторінка після оновлення плагіна

  • Симптом: Сайт стає порожнім одразу після оновлення плагіна.
  • Корінь: Фатал через несумісність версії PHP, відсутнє розширення або погане автозавантаження/повторне оголошення класу.
  • Виправлення: Вимкніть плагін через WP-CLI; перевірте версію PHP; відкотіть плагін; тестуйте оновлення в середовищі з паритетом.

3) Біла сторінка лише для залогінених користувачів

  • Симптом: Анонімні користувачі бачать сайт; адміни бачать WSOD.
  • Корінь: Плагіни для адмінки, віджети панелі або відмінності ліміту пам’яті (WP_MAX_MEMORY_LIMIT).
  • Виправлення: Тимчасово збільште пам’ять для адмінки; вимкніть адмінські плагіни; перевірте логи PHP-FPM на вичерпання пам’яті; профілюйте повільні адмін‑сторінки.

4) Білий екран періодично під навантаженням

  • Симптом: Працює іноді; біліє під час піків.
  • Корінь: Вичерпання воркерів PHP-FPM, таймаути upstream, лиміти підключень до БД, затримки Redis або повільне зберігання.
  • Виправлення: Перевірте таймаути Nginx upstream, pm.max_children в PHP-FPM, Threads_connected у БД, латентність Redis. Зменшіть конкуренцію або оптимізуйте повільні шляхи.

5) WSOD почався «після очищення кешів»

  • Симптом: Очищення кешу, здається, запускає порожні сторінки.
  • Корінь: Плагін кешу записує на диск/tmp, але диск повний або файлову систему змонтовано лише для читання; або неправильні права на wp-content.
  • Виправлення: Перевірте диск/inode, прапори монтування, права та власника wp-content; виправте зберігання перед відновленням кешів.

6) WSOD після увімкнення «зміцнення безпеки»

  • Симптом: Сайт білий після увімкнення правила WAF, плагіна безпеки або зміни прав файлів.
  • Корінь: Блокує admin-ajax/admin-post, REST‑ендпоїнти або забороняє PHP читати файли тем/плагінів.
  • Виправлення: Перегляньте логи WAF; відкотіть права до відомого хорошого стану; переконайтеся, що PHP‑користувач може читати код і записувати uploads/cache там, де потрібно.

Чек-листи / покроковий план (відновити сервіс, потім запобігти)

Фаза 1: Відновлення сервісу (пріоритет: вплив на користувачів)

  1. Підтвердіть режим WSOD за допомогою curl (статус, розмір, час відповіді).
  2. Обійдіть кеші/CDN і протестуйте origin.
  3. Прочитайте журнали веб‑сервера і PHP-FPM на предмет фаталів і таймаутів.
  4. Вимкніть усі плагіни (WP-CLI). Повторно протестуйте.
  5. Переключіться на тему за замовчуванням. Повторно протестуйте.
  6. Перевірте диск/inode і стан монтування (повний/readonly швидко вбиває WordPress).
  7. Перевірте підключення до БД і насичення підключень.
  8. Відкотіть останню зміну (плагін/тема/версія PHP), якщо причина не очевидна протягом 30 хвилин.

Фаза 2: Визначення точної кореневої причини (пріоритет: не допустити повтору)

  1. Захопіть перший фатальний стек‑трек (WordPress debug log або PHP error log).
  2. Відтворіть у контрольованому середовищі з тим самим набором плагінів/тем і версією PHP.
  3. Визначте тригерний запит: головна, шорткод, cron, admin-ajax, REST‑маршрут.
  4. Виправте баг або замініть компонент; додайте регресійний тест (навіть простий синтетичний curl, що перевіряє непорожнє HTML).
  5. Розгляньте коригування пам’яті/таймаутів — лише після розуміння шляху виконання.

Фаза 3: Запобігання (пріоритет: майбутній ви може спати)

  • Паритет staging: той самий список плагінів, та сама версія PHP, ті самі кеш‑шари.
  • Централізовані логи: Nginx/Apache + PHP-FPM + WordPress debug log (з ротацією).
  • Дисципліна деплою: перезапускайте PHP-FPM коли OPcache validation вимкнено; уникайте «часткових деплоїв».
  • Реальні health-чекі: зачіпайте динамічні endpoint-и і перевіряйте розмір тіла відповіді, а не тільки статус.
  • Моніторинг зберігання: сповіщення про відсоток диска, відсоток inode і події переходу в read-only.

Питання й відповіді

1) Чому я бачу білу сторінку з HTTP 200?

Тому що запит завершується на HTTP‑рівні, але PHP не генерує вивід — часто через фатал, буферизацію або обрив виводу. Логи показують правду.

2) Чи варто вмикати display_errors у продакшні?

Ні. Краще логувати помилки. Публічний вивід помилок — це витік інформації і може ще більше зламати відповіді. Увімкніть WP_DEBUG_LOG і тримайте WP_DEBUG_DISPLAY вимкненим.

3) Який найшвидший спосіб виключити плагіни?

WP-CLI: wp plugin deactivate --all. Якщо WP-CLI немає, перейменуйте wp-content/plugins і протестуйте знову.

4) Чи може тема справді спричинити WSOD?

Так. Теми виконують PHP. Фатал у functions.php або в шаблоні може затемнити сайт так само ефективно, як і плагін.

5) Чому WSOD трапляється лише іноді?

Перервний WSOD зазвичай означає конкуренцію за ресурси: вичерпання воркерів PHP-FPM, максимальні підключення до БД, латентність кешу або зависання зберігання. Шукайте таймаути і метрики насичення, а не тільки фатали.

6) Якщо wp-admin теж білий — що це значить?

Це вказує на глобальну проблему: must-use плагін, невідповідність файлів ядра, падіння PHP-розширення, відмова БД або проблеми з правами/записом. Почніть з логів, потім вимикайте плагіни/тему через файлову систему або БД.

7) Як переключити тему, якщо WP-CLI недоступний?

Змініть опції бази даних template та stylesheet на тему за замовчуванням. Або встановіть WP-CLI — це безпечніше за ручний SQL, коли ви під стресом.

8) Чи може OPcache спричинити WSOD?

Опосередковано — так: застарілий байткод може продовжувати виконувати зламаний код після того, як ви «виправили» файли. Якщо ви деплойите без перезапуску PHP-FPM і валідація часових міток OPcache вимкнена, ви ризикуєте.

9) Чи є підвищення ліміту пам’яті дійсним вирішенням?

Як тимчасовий захід — іноді. Як остаточне вирішення — рідко. Якщо запит раптом вимагає вдвічі більше пам’яті, щось змінилося: оновився плагін, запит, нескінченний цикл або зріст навантаження.

10) Як зупинити CDN від кешування порожньої сторінки?

Очистіть уражені шляхи і переконайтеся, що origin не повертає пусті 200 під час відмов. Налаштуйте правила кешу на краю, щоб вони враховували статуси помилок, і розгляньте синтетичну перевірку, що валідовує непорожнє HTML.

Наступні кроки (практично, не натхненно)

Зробіть це наступного разу, коли з’явиться WSOD:

  1. Запустіть curl і підтвердіть статус, розмір і чи дивитесь ви на кеш краю чи на origin.
  2. Перечитайте логи Nginx/Apache і PHP-FPM перед будь-якими іншими змінами.
  3. Вимкніть плагіни, переключіть тему і повторно протестуйте — швидка ізоляція краща за повільне розмірковування.
  4. Перевірте диск/inode і стан монтування. Проблеми зі зберіганням витрачають години, бо виглядають «додатково».
  5. Після відновлення запишіть єдину кореневу причину, тригерну зміну і запобіжний механізм, який ви додаєте.

Якщо ви додасте лише один запобіжник: зробіть так, щоб ваш health‑check запитував динамічну сторінку WordPress і провалювався, якщо тіло порожнє. WSOD любить ховатися за «200 OK». Не давайте йому такої можливості.

← Попередня
Читання лише метаданих у ZFS: як special vdev змінює правила гри
Наступна →
DLSS пояснено: найефективніший трюк для FPS десятиліття

Залишити коментар