Біла сторінка смерті — це спосіб 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: Відновлення сервісу (пріоритет: вплив на користувачів)
- Підтвердіть режим WSOD за допомогою curl (статус, розмір, час відповіді).
- Обійдіть кеші/CDN і протестуйте origin.
- Прочитайте журнали веб‑сервера і PHP-FPM на предмет фаталів і таймаутів.
- Вимкніть усі плагіни (WP-CLI). Повторно протестуйте.
- Переключіться на тему за замовчуванням. Повторно протестуйте.
- Перевірте диск/inode і стан монтування (повний/readonly швидко вбиває WordPress).
- Перевірте підключення до БД і насичення підключень.
- Відкотіть останню зміну (плагін/тема/версія PHP), якщо причина не очевидна протягом 30 хвилин.
Фаза 2: Визначення точної кореневої причини (пріоритет: не допустити повтору)
- Захопіть перший фатальний стек‑трек (WordPress debug log або PHP error log).
- Відтворіть у контрольованому середовищі з тим самим набором плагінів/тем і версією PHP.
- Визначте тригерний запит: головна, шорткод, cron, admin-ajax, REST‑маршрут.
- Виправте баг або замініть компонент; додайте регресійний тест (навіть простий синтетичний curl, що перевіряє непорожнє HTML).
- Розгляньте коригування пам’яті/таймаутів — лише після розуміння шляху виконання.
Фаза 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:
- Запустіть curl і підтвердіть статус, розмір і чи дивитесь ви на кеш краю чи на origin.
- Перечитайте логи Nginx/Apache і PHP-FPM перед будь-якими іншими змінами.
- Вимкніть плагіни, переключіть тему і повторно протестуйте — швидка ізоляція краща за повільне розмірковування.
- Перевірте диск/inode і стан монтування. Проблеми зі зберіганням витрачають години, бо виглядають «додатково».
- Після відновлення запишіть єдину кореневу причину, тригерну зміну і запобіжний механізм, який ви додаєте.
Якщо ви додасте лише один запобіжник: зробіть так, щоб ваш health‑check запитував динамічну сторінку WordPress і провалювався, якщо тіло порожнє. WSOD любить ховатися за «200 OK». Не давайте йому такої можливості.