Komunikat „W witrynie wystąpił błąd krytyczny”, biały ekran albo HTTP 500 mówi niewiele o przyczynie problemu. Znacznie więcej informacji zwykle znajduje się w logu PHP lub w debug.log WordPressa: typ błędu, plik, numer linii i czas wystąpienia. Osobno sprawdź komunikat Error establishing a database connection, gdy WordPress nie łączy się z bazą.
Najważniejsze jest jednak znalezienie właściwego logu. Na jednym hostingu mogą równocześnie istnieć log serwera WWW, log PHP-FPM, systemowy error_log i plik diagnostyczny WordPressa. Nie wszystkie opisują ten sam etap obsługi żądania.
Przy awarii zacznij od czasu wystąpienia problemu i konkretnego żądania. Log jest najbardziej użyteczny wtedy, gdy potrafisz powiązać wpis z czynnością, którą przed chwilą wykonałeś.
error_log i debug.log to nie to samo
PHP może zapisywać komunikaty diagnostyczne do logu skonfigurowanego przez serwer. Za takie zachowanie odpowiadają między innymi ustawienia log_errors i error_log. Dokumentacja PHP zaleca na serwerach produkcyjnych logowanie błędów zamiast ich publicznego wyświetlania.
WordPress ma dodatkowo własny mechanizm debugowania. Po włączeniu WP_DEBUG można użyć WP_DEBUG_LOG, aby zapisywać komunikaty do pliku — domyślnie wp-content/debug.log — albo do wskazanej własnej ścieżki. WP_DEBUG_DISPLAY steruje natomiast tym, czy komunikaty mają pojawiać się w generowanej stronie.
| Źródło | Co zwykle zawiera | Kiedy jest najbardziej przydatne |
|---|---|---|
| PHP / server error log | Błędy i ostrzeżenia PHP zapisane przez środowisko serwera | Gdy WordPress nie zdąży się poprawnie uruchomić albo problem dotyczy samego PHP |
wp-content/debug.log | Komunikaty zbierane przy aktywnym debugowaniu WordPressa | Przy diagnozie wtyczek, motywu i kodu WordPressa |
| Log serwera WWW | Żądania HTTP i błędy obsługi przez Apache, NGINX lub LiteSpeed | Gdy trzeba rozdzielić problem HTTP od błędu aplikacji |
Dokładne nazwy i lokalizacje zależą od hostingu. Plik o nazwie error_log w katalogu domeny nie jest obowiązkowym standardem wszystkich serwerów.
Na produkcji loguj błędy zamiast pokazywać je użytkownikowi
PHP rozdziela zapisywanie błędów od ich wyświetlania. log_errors decyduje o logowaniu, a display_errors o umieszczaniu komunikatów w odpowiedzi generowanej dla użytkownika.
Na publicznej stronie szczegółowy komunikat PHP może ujawnić ścieżkę pliku, nazwy klas, strukturę aplikacji, a w niektórych przypadkach inne dane przydatne podczas ataku. Na środowisku produkcyjnym bezpieczniejszym ustawieniem jest logowanie błędów przy wyłączonym ich publicznym wyświetlaniu.
W WordPressie podobny układ można uzyskać przez zapis do logu bez wyświetlania komunikatów na stronie:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
WP_DEBUG_DISPLAY=false kontroluje sposób obsługi komunikatów przez WordPress, ale nie zastępuje konfiguracji samego PHP. Jeżeli PHP ma aktywne display_errors, na produkcji trzeba również upewnić się, że publiczne wyświetlanie błędów jest wyłączone po stronie środowiska PHP.
Przy diagnostyce produkcji lepiej, jeśli log może być zapisany poza publicznym katalogiem strony; WP_DEBUG_LOG może wskazywać własną ścieżkę zamiast domyślnego wp-content/debug.log.
WP_DEBUG_LOG i WP_DEBUG_DISPLAY działają w powiązaniu z aktywnym WP_DEBUG. Tryby debugowania WordPressa są przeznaczone przede wszystkim do kontrolowanej diagnostyki, a nie do pozostawienia bez nadzoru na produkcji.
Jak czytać pojedynczy wpis błędu?
Najbardziej wartościowy wpis zwykle odpowiada na cztery pytania:
- kiedy wystąpił problem,
- jaki jest typ błędu,
- jaki plik został wskazany,
- w której linii wykryto problem.
Przykładowy komunikat może wyglądać podobnie do:
PHP Fatal error: Uncaught TypeError: ...
in /home/user/domains/example.pl/public_html/wp-content/plugins/example/example.php:184
Najważniejsze są tutaj nie wszystkie techniczne szczegóły wyjątku, ale przede wszystkim Fatal error, ścieżka do pliku, nazwa komponentu oraz numer linii.
Jeżeli wskazana ścieżka prowadzi do:
wp-content/plugins/nazwa-wtyczki/— pierwszy trop prowadzi do tej wtyczki;wp-content/themes/nazwa-motywu/— problem może dotyczyć motywu lub jego integracji;wp-content/mu-plugins/— trzeba uwzględnić must-use pluginy;- własnego katalogu aplikacji — diagnoza dotyczy kodu wdrożonego poza standardowym rdzeniem WordPressa.
Ścieżka wskazuje miejsce wykrycia błędu, ale nie zawsze jego pierwotną przyczynę. Wadliwa wartość mogła zostać przekazana z innego komponentu kilka wywołań wcześniej.
Fatal error, warning i deprecated oznaczają różne rzeczy
Nie każdy wpis w logu oznacza awarię strony.
Fatal error
Błąd krytyczny zatrzymuje wykonywanie danego żądania. To właśnie taki problem najczęściej koreluje z HTTP 500, pustą odpowiedzią albo ekranem błędu WordPressa.
Warning
Ostrzeżenie sygnalizuje problem, ale wykonanie kodu może trwać dalej. Duża liczba warningów nadal może być ważna diagnostycznie, szczególnie jeśli pojawiły się po aktualizacji albo dotyczą operacji wykonywanej setki razy.
Deprecated
Komunikat o przestarzałej konstrukcji zwykle informuje, że kod korzysta z rozwiązania, które nadal działa, ale zostało oznaczone do zmiany lub usunięcia w przyszłości.
Sam wpis Deprecated nie jest więc równoważny z błędem powodującym niedostępność strony. Może jednak wskazywać stary plugin, motyw albo własny kod wymagający aktualizacji przed kolejną zmianą PHP.
Najpierw znajdź pierwszy istotny błąd dotyczący testowanej operacji
Jedno uszkodzone żądanie może wygenerować wiele komunikatów. Na działającym serwerze wpisy z kilku równoległych żądań mogą się dodatkowo przeplatać.
Dlatego nie chodzi wyłącznie o pierwszy wpis po określonej godzinie. Lepsza procedura to:
- zanotować możliwie dokładny czas testu,
- wykonać jedną problematyczną czynność,
- odczytać wpisy z możliwie wąskiego przedziału czasu,
- jeśli log zawiera URI, identyfikator żądania lub inne dane korelacyjne, zawęzić wpisy do testowanej operacji,
- znaleźć pierwszy istotny błąd dotyczący tego samego żądania,
- dopiero potem analizować kolejne wpisy jako możliwe skutki.
Przy dużym logu takie zawężenie jest znacznie skuteczniejsze niż wyszukiwanie losowych słów typu error.
Jak powiązać błąd z wtyczką albo motywem?
Jeżeli log wskazuje plik w katalogu konkretnej wtyczki, warto sprawdzić, co zmieniło się bezpośrednio przed awarią. Typowe sytuacje to aktualizacja pluginu, zmiana PHP, aktywacja nowego rozszerzenia albo uruchomienie rzadko wykonywanej operacji.
Nie należy jednak automatycznie uznawać właściciela pliku wskazanego w ostatniej linii za autora błędu. Integracja może przekazać nieprawidłowe dane do innej wtyczki albo funkcji WordPressa.
Praktyczna kolejność wygląda tak:
- zidentyfikuj komponent widoczny w stack trace lub ścieżce,
- sprawdź jego wersję i ostatnie zmiany,
- ustal, czy błąd da się powtórzyć,
- porównaj z działaniem po wyłączeniu podejrzanego komponentu na stagingu lub w kontrolowanych warunkach,
- jeżeli problem pojawił się po zmianie PHP, sprawdź zgodność rozszerzenia z nową wersją.
Przy problemach wydajnościowych sam fatal error może być tylko końcowym objawem. Jeśli w logu pojawia się wyczerpanie pamięci albo przekroczenie czasu wykonywania, warto zestawić wpis z poradnikiem o limitach PHP na hostingu.
Dwa częste błędy limitów PHP w logach
Allowed memory size exhausted
Komunikat:
Allowed memory size of ... bytes exhausted
oznacza, że wykonywany skrypt PHP próbował przydzielić więcej pamięci, niż pozwalał jego aktywny limit.
Nie odpowiada jeszcze na pytanie, dlaczego zużycie było tak duże. Powodem może być pojedyncza ciężka operacja, duży import, obróbka obrazu, pobranie bardzo dużego zestawu danych albo błąd powodujący niekontrolowany wzrost zużycia pamięci.
Po zidentyfikowaniu takiego wpisu najpierw warto ustalić operację i komponent, a dopiero później decydować o zmianie memory_limit.
Maximum execution time exceeded
Log może również zawierać informację o przekroczeniu maksymalnego czasu wykonywania PHP.
Taki wpis wskazuje ograniczenie po stronie interpretera, ale całe żądanie HTTP może mieć również timeout w PHP-FPM, serwerze WWW, reverse proxy albo innej warstwie infrastruktury.
Jeżeli przeglądarka otrzymuje błąd po określonym czasie, trzeba ustalić, która warstwa przerwała żądanie i co kod wykonywał tak długo, zamiast automatycznie zwiększać wyłącznie max_execution_time.
„W witrynie wystąpił błąd krytyczny” i Recovery Mode
WordPress ma mechanizm Recovery Mode obsługujący część krytycznych błędów PHP. Gdy wykryje obsługiwany fatal error podczas zwykłego ładowania strony, może wyświetlić użytkownikowi komunikat o problemie i wysłać administratorowi wiadomość z linkiem umożliwiającym wejście w tryb odzyskiwania.
W takim trybie wadliwa wtyczka lub motyw może zostać wstrzymany dla sesji administratora, co pozwala zalogować się i przeprowadzić diagnostykę. Recovery Mode nie zastępuje jednak logu. Informacja z logu nadal pomaga ustalić konkretny plik i typ błędu.
Brak wiadomości z linkiem do Recovery Mode również nie dowodzi, że fatal error nie wystąpił. Problem z dostarczeniem wiadomości może pojawić się na przykład wtedy, gdy awaria wystąpi zanim załaduje się plugin zmieniający sposób wysyłki poczty. Osobno sprawdź problemy z wysyłką e-maili WordPressa, jeżeli nie działa więcej niż jeden typ powiadomień.
Bezpieczne używanie debug.log na produkcji
Włączenie debugowania na stronie generującej dużo warningów może stworzyć duży plik w krótkim czasie. Diagnostyka powinna mieć więc konkretny początek i koniec.
Dobrą procedurą jest:
- zachować stary log, jeśli jest potrzebny do porównania,
- włączyć diagnostykę,
- odtworzyć problem,
- pobrać potrzebny fragment,
- wyłączyć tymczasowe ustawienia po zakończeniu testu.
Plik diagnostyczny może zawierać ścieżki serwerowe, fragmenty zapytań, adresy URL, nazwy komponentów, identyfikatory i inne dane, których użytkownik witryny nie potrzebuje widzieć.
Jeżeli debug.log znajduje się w katalogu dostępnym przez WWW, trzeba uwzględnić sposób, w jaki serwer ogranicza do niego dostęp. Przy diagnostyce produkcji lepszym rozwiązaniem jest własna ścieżka poza publicznym webrootem, jeżeli środowisko hostingowe na to pozwala.
Przed przekazaniem fragmentu logu supportowi albo programiście warto również sprawdzić, czy nie zawiera danych uwierzytelniających, tokenów, danych klientów lub innych informacji zbędnych do rozwiązania problemu.
Log PHP a HTTP 500, 503 i 508
Kod odpowiedzi HTTP nie wystarcza do ustalenia przyczyny.
HTTP 403 może zostać zwrócony przed uruchomieniem PHP, dlatego brak wpisu w logu aplikacji nie wyklucza blokady w konfiguracji serwera, WAF-ie albo reverse proxy.
HTTP 500 może być skutkiem nieobsłużonego błędu aplikacji, błędu składni, konfiguracji serwera albo innego problemu wewnętrznego. Jeżeli przyczyną jest PHP, log często wskaże konkretny fatal error.
HTTP 503 może powstać wtedy, gdy aplikacja albo infrastruktura tymczasowo nie może obsłużyć żądania. Nie każdy 503 zostawi więc charakterystyczny fatal error PHP.
HTTP 508 wymaga szczególnej ostrożności. W RFC 5842 kod 508 oznacza Loop Detected w kontekście WebDAV, natomiast CloudLinux używa strony 508 Resource Limit Reached między innymi przy przekroczeniu limitu Entry Processes. Sam numer kodu trzeba więc interpretować w kontekście platformy operatora i jej logów.
Przy błędach związanych z obciążeniem dobrze zestawić log aplikacji z danymi z diagnostyki zasobów hostingu. Jeden pokazuje, co zgłosił kod, drugi może pomóc ocenić, co działo się z zasobami konta.
Brak błędów w logu nie wyklucza problemu z wydajnością
Wolne zapytania SQL, zewnętrzne API, kolejka do PHP workers albo ograniczenia CPU i I/O mogą spowalniać stronę bez generowania fatal errorów PHP. Log błędów nie zastępuje więc profilowania ani danych o wykorzystaniu zasobów.
Przy ogólnie wolnej witrynie użyteczniejszym punktem startowym może być poradnik Dlaczego WordPress działa wolno — hosting czy sama strona?.
Praktyczna procedura diagnozy z logiem
- Zapisz godzinę rozpoczęcia testu.
- Wykonaj jedną czynność wywołującą problem.
- Sprawdź log PHP dostępny w panelu lub środowisku serwera.
- Jeżeli potrzebujesz diagnostyki WordPressa, użyj kontrolowanego WP_DEBUG_LOG.
- Zawęź wpisy do czasu i, jeśli to możliwe, tego samego żądania lub URI.
- Znajdź pierwszy istotny błąd dotyczący testowanej operacji.
- Zapisz typ błędu, plik i numer linii.
- Powiąż ścieżkę z wtyczką, motywem albo własnym kodem.
- Sprawdź, co zmieniło się przed wystąpieniem problemu.
- Powtórz test po jednej konkretnej zmianie.
- Po diagnozie wyłącz tymczasowe ustawienia debugowania.
Taka procedura daje bardziej wiarygodny wynik niż jednoczesne wyłączanie kilku wtyczek, zwiększanie wszystkich limitów PHP i czyszczenie każdego cache.
Najważniejsze wnioski
error_logPHP idebug.logWordPressa mogą opisywać inne warstwy diagnostyki;- na produkcji błędy lepiej logować niż publicznie wyświetlać;
WP_DEBUG_DISPLAY=falsenie zastępuje ustawienia PHPdisplay_errors=Off;WP_DEBUG_LOGmoże wskazywać własną ścieżkę, co pozwala zapisać log poza publicznym webrootem;- najbardziej użyteczny wpis trzeba powiązać z konkretnym czasem i testowaną operacją;
- ścieżka do pliku pomaga wskazać komponent, ale nie zawsze dowodzi, że to on jest pierwotną przyczyną;
- fatal error, warning i deprecated mają różne znaczenie;
- błąd pamięci lub czasu wykonywania jest punktem wyjścia do diagnostyki, a nie automatycznym poleceniem zwiększenia limitu;
- Recovery Mode może pomóc odzyskać dostęp po części fatal errorów, ale nie zastępuje analizy logu;
- kod HTTP 508 trzeba interpretować w kontekście platformy, bo może oznaczać coś innego w WebDAV i CloudLinux;
- brak wpisów w logu nie wyklucza problemów z wydajnością;
- pliki diagnostyczne nie powinny pozostawać publicznie dostępne ani zawierać niepotrzebnie udostępnianych danych.
Źródła
- PHP Manual — Errors and Logging Configuration —
error_reporting,display_errors,log_errorsierror_log. - PHP Manual — Error Basics — wyświetlanie i logowanie błędów oraz zastosowanie logów na produkcji.
- PHP Manual — error_log() — zapis komunikatów do mechanizmu logowania PHP.
- WordPress Developer Resources — Debugging in WordPress —
WP_DEBUG,WP_DEBUG_LOG, własna ścieżka logu iWP_DEBUG_DISPLAY. - WordPress Developer Resources — wp-config.php — konfiguracja debugowania WordPressa.
- WordPress Documentation — Recovery Mode — zachowanie WordPressa po wybranych fatal errorach PHP.
- RFC 5842 — Binding Extensions to WebDAV — definicja HTTP 508
Loop Detected. - CloudLinux OS — Limits — użycie 508
Resource Limit Reachedprzy przekroczeniu limitu Entry Processes.