wp-cron nie działa i maile nie wychodzą? Sprawdź crontab i zabezpiecz zadania
wp-cron nie działa, a maile z WordPressa nie wychodzą? Sprawdź crontab w 5 minut, poznaj pułapkę „crontab -” i zabezpiecz zadania cykliczne strony.

Strona się otwiera, płatności przechodzą, panel WordPressa działa. A mimo to nie wychodzą przypomnienia o zajęciach, powiadomienia o zamówieniach ani maile o zaległych ratach. Rzeczy, które powinny dziać się same, po prostu przestają się dziać. Jeśli trafiłeś tu, bo wp-cron nie działa i maile nie wychodzą, a niczego nie zmieniałeś – ten poradnik może oszczędzić Ci kilka godzin szukania w złym miejscu.
Bardzo często przyczyną nie jest wtyczka ani serwer pocztowy, tylko pusty crontab. A najczęstszy sposób, w jaki crontab robi się pusty, to jeden niewinnie wyglądający potok, który można znaleźć w niemal każdym poradniku.
Kontekst: na czym stoją automatyzacje WordPressa
Na stronach, które żyją z automatyzacji – platformach kursowych, sklepach, systemach zapisów – wbudowany wp-cron zwykle wyłącza się stałą DISABLE_WP_CRON. Wbudowany mechanizm odpala zadania przy okazji wejścia użytkownika na stronę, więc przy małym ruchu potrafią one czekać godzinami, a przy dużym obciążają serwer. Zamiast tego każda strona ma własny wpis w systemowym cronie:
*/5 * * * * cd /sciezka/do/strony && wp cron event run --due-now --quiet
To jest fundament. Na tych wpisach stoją przypomnienia do klientów, kolejki mailowe, odnawianie subskrypcji, wystawianie faktur i synchronizacje z zewnętrznymi systemami. Przy kilku stronach na jednym serwerze takich linii jest kilka albo kilkanaście, obok zadań serwisowych.
Diagnoza krok po kroku: dlaczego wp-cron nie działa, skoro nic się nie zmieniło
Hipoteza 1: padła wtyczka mailowa albo SMTP
Pierwszy odruch, bo objawem jest brak maili. Zacznij od testu wysyłki i logu SMTP. Jeśli test przechodzi, konfiguracja jest nietknięta, a problem dotyczy kilku stron naraz, z różnymi wtyczkami do poczty, wspólny mianownik leży niżej niż pojedyncza strona.
Hipoteza 2: coś w samym WordPressie
Sprawdź kolejkę zadań:
wp cron event list --fields=hook,next_run_relative
Jeśli zadania są na miejscu, ale z terminami z przeszłości, masz pierwszą konkretną wskazówkę: WordPress wie, co ma zrobić, ale nikt go o to nie prosi. Problem nie siedzi w aplikacji, tylko w tym, co ją uruchamia.
Hipoteza 3, czyli sprawdzenie, które trzeba było zrobić jako pierwsze
crontab -l
Jeśli w odpowiedzi widzisz jedną linijkę zamiast kilku czy kilkunastu albo nie widzisz nic, crontab został wyczyszczony. I zwykle nie zostawia po sobie żadnego śladu: żadnego błędu w logach, żadnego maila z ostrzeżeniem, żadnego alertu.
Moment odkrycia: „crontab -” nadpisuje wszystko i nie protestuje
Typowy scenariusz: mały, jednorazowy skrypt ma uruchomić się raz wieczorem, a potem usunąć z crona własny wpis. Usuwa go wzorcem, który można znaleźć w niemal każdym poradniku:
crontab -l | grep -v przypomnienie.sh | crontab -
Polecenie
crontab -nie usuwa jednej linii. Ono zastępuje cały crontab tym, co dostanie na wejściu. Jeśli lewa strona potoku zwróci pusty strumień, prawa strona posłusznie zapisze pusty crontab i zakończy się sukcesem. Bez błędu, bez ostrzeżenia, bez pytania.
A lewa strona potrafi zwrócić pustkę z banalnych powodów. Skrypt uruchomiony z crona ma inne środowisko niż sesja w terminalu. Polecenie może nie trafić na właściwą binarkę w PATH. Zdalne połączenie może się urwać. Zmienna, do której ktoś wcześniej wczytał crontab, może być pusta po nieudanym odczycie. Wystarczy jedno z tych zdarzeń.
Ten sam efekt daje drugi popularny wzorzec, ze zmienną: crontab wczytany do zmiennej, nowa linia doklejona na końcu, całość przekazana do crontab -. Jeśli zmienna jest pusta po nieudanym odczycie, znikają wszystkie wpisy naraz. Różne skrypty, jeden mechanizm.
Rozwiązanie: crontab wyłącznie przez bramkę z walidacją
Odtworzenie wpisów to kilka minut, jeśli masz z czego je odtworzyć. Ważniejsze, żeby to samo nie mogło się powtórzyć. Nie chodzi o notatkę „uważaj na crontab”, tylko o zmianę, która działa także wtedy, gdy nikt o niej nie pamięta. Tak zabezpieczamy zadania cykliczne na stronach, którymi się opiekujemy – monitoring crona jest standardem w naszej opiece nad stronami WordPress.
1. Jedna droga zapisu: skrypt-bramka
Żaden skrypt nie powinien pisać do crontaba bezpośrednio. Wszystko przechodzi przez jeden skrypt-bramkę, który w środku ma:
- kopię obecnego crontaba do pliku przed jakąkolwiek zmianą,
- blokadę zapisu pustej albo podejrzanie krótkiej zawartości,
- minimalną liczbę wpisów wp-cron, poniżej której zapis jest odrzucany,
- blokadę ubytku więcej niż kilku wpisów naraz,
- ponowne liczenie po zapisie i automatyczne przywrócenie kopii, gdy coś się nie zgadza,
- alert mailem przy każdej odrzuconej próbie.
Sedno tej walidacji mieści się w kilku liniach. Warto je mieć u siebie, nawet jeśli masz jedną stronę:
KOPIA=~/crontab-kopia-$(date +%F-%H%M).txt
crontab -l > "$KOPIA" 2>/dev/null
LICZ=$(grep -c . nowy-crontab.txt)
[ "$LICZ" -ge "$MINIMUM" ] || { echo "BLAD: crontab podejrzanie krotki"; exit 1; }
crontab nowy-crontab.txt
[ "$(crontab -l | grep -c .)" -ge "$MINIMUM" ] || crontab "$KOPIA"
Zwróć uwagę, że pracujemy na pliku, a nie na zmiennej w potoku: crontab -l > plik, edycja pliku, crontab plik. Każdy krok da się wtedy sprawdzić osobno, a pusty plik widać gołym okiem.
Pułapka przy alertach: sprawdź, czy na serwerze w ogóle jest polecenie mail. Na wielu hostingach go nie ma, jest tylko sendmail. Skrypt kończący się potokiem do mail przechodzi wtedy test składni, uruchamia się bez widocznego błędu i po cichu nie wysyła nic. Każdy skrypt alarmowy testuj jednym prawdziwym uruchomieniem.
2. Strażnik, który sprawdza, czy wpisy istnieją
Sama kopia nie wystarczy, bo ktoś musi zauważyć brak. Co kwadrans uruchamia się strażnik, który przechodzi po katalogach wszystkich stron i sprawdza, czy każda z nich ma swój wpis wp-cron. Brakujący dopisuje przez tę samą bramkę i melduje o tym.
Pułapka: jeśli strażnik sam jest wpisem w crontabie, wyczyszczony crontab zabiera go ze sobą. Dlatego to samo sprawdzenie warto odpalać także z drugiej maszyny, spoza hostingu, na przykład co 15 minut. Takie przenoszenie powtarzalnych zadań poza jeden punkt awarii to codzienność w automatyzacjach, które budujemy dla firm.
3. Blokada wzorca, zanim w ogóle trafi do skryptu
Ostatnia warstwa to zakaz samego wzorca | crontab -. Sama kontrola grepem po katalogu skryptów na serwerze nie wystarcza, bo nie widzi narzędzi uruchamianych z innych miejsc. Skuteczniejsza jest automatyczna blokada, która odrzuca zapis do crontaba potokiem, zanim komenda w ogóle się wykona. Mechanizm takich blokad opisuje wpis o hookach Claude Code blokujących groźne komendy.
Efekt: błąd może się zdarzyć, ale nie dociera do klientów
Z trzema warstwami pusty crontab przestaje być cichą awarią. Bramka odrzuca podejrzany zapis, a gdy wpisy znikną inną drogą, strażnik z zewnątrz odtwarza je w ciągu kwadransa, zanim ktokolwiek zauważy brak maili. Zaległe zadania WordPressa wykonują się przy pierwszym przebiegu.
To jest właściwa miara takiej zmiany: nie to, że błąd już nigdy się nie zdarzy, tylko to, że gdy się zdarzy, nie dotrze do klientów.
Jak sprawdzić to u siebie
- Policz wpisy:
crontab -l | grep -c .. Zapisz tę liczbę. Jeśli jej nie znasz, nie zauważysz, gdy spadnie. - Poszukaj niebezpiecznego wzorca we własnych skryptach i narzędziach, także tych na komputerze:
grep -rn "| *crontab -" ~/bin ~/skrypty. - Sprawdź, czy WordPress ma zaległe zadania:
wp cron event list --fields=hook,next_run_relative. Terminy z przeszłości to sygnał, że nikt ich nie odpala. - Jeśli w
wp-config.phpmaszDISABLE_WP_CRON, upewnij się, że istnieje systemowy wpis, który go zastępuje. - Zrób kopię crontaba do pliku już teraz i dołącz ją do backupu.
- Dodaj monitoring z innej maszyny: raz na kwadrans albo raz na godzinę sprawdzenie liczby wpisów i powiadomienie, gdy jest ich mniej, niż powinno.
- Przetestuj alert prawdziwym uruchomieniem, a nie samym sprawdzeniem składni.
Najważniejsza zasada
Operacja, która potrafi po cichu skasować fundament, nie może być dostępna „z palca”. Musi mieć jedną drogę wykonania, walidację w środku i sprawdzenie po zapisie. Do tego potrzebny jest ktoś, kto patrzy z zewnątrz, bo mechanizm ochronny, który żyje w tym samym miejscu co awaria, ginie razem z nią. A „jednorazowy” skrypt to najgroźniejszy przypadek: działa raz, wieczorem, bez nikogo przy klawiaturze i nikt go już drugi raz nie przetestuje.
FAQ
Czym różni się wp-cron od systemowego crona?
Wbudowany wp-cron uruchamia zadania przy okazji wejścia użytkownika na stronę, więc przy małym ruchu potrafią one czekać godzinami. Systemowy cron uruchamia je o stałej porze, niezależnie od ruchu. Dlatego na stronach z automatyzacjami wyłączamy wbudowany mechanizm i zastępujemy go wpisem systemowym.
Jak sprawdzić, czy zadania WordPressa się wykonują?
Najprościej komendą wp cron event list --fields=hook,next_run_relative. Jeśli przy zadaniach widzisz terminy z przeszłości, kolejka czeka i nikt jej nie uruchamia. Bez dostępu do konsoli podobną listę pokazują wtyczki do podglądu zadań cron.
Dlaczego polecenie crontab z minusem jest niebezpieczne?
Bo zastępuje cały crontab tym, co dostanie na wejściu. Pusty strumień oznacza pusty crontab, a polecenie kończy się sukcesem, bez ostrzeżenia. Błąd ujawnia się dopiero wtedy, gdy przestają działać zadania.
Jak bezpiecznie usunąć jeden wpis z crontaba?
Pracuj na pliku: crontab -l > plik, edycja pliku, sprawdzenie liczby linii, crontab plik. Po zapisie policz wpisy jeszcze raz i porównaj z oczekiwaną liczbą. Kopię zrób przed pierwszym krokiem.
Czy wystarczy sam backup crontaba?
Nie. Backup ratuje dane, ale ktoś musi zauważyć, że trzeba go przywrócić. Bez monitoringu liczby wpisów dowiesz się o problemie od klienta, który nie dostał maila.
Maile z WordPressa nie wychodzą, ale crontab jest w porządku. Co dalej?
Wtedy sprawdź kolejno: czy zadanie wysyłki jest w kolejce wp-cron, czy test wysyłki z konsoli przechodzi, czy wtyczka SMTP ma poprawne dane i czy domena ma ustawione rekordy SPF i DKIM. Kolejność ma znaczenie: najpierw to, co uruchamia wysyłkę, potem sama wysyłka.
Masz kilka stron i nie wiesz, czy ich automatyzacje działają? Napisz do nas
Jeśli utrzymujesz strony WordPress z przypomnieniami, subskrypcjami albo kolejkami maili i nie masz pewności, czy zadania faktycznie się wykonują, to nie jest pytanie „czy”, tylko „kiedy”. Zajmujemy się tym na co dzień: monitoring zadań cyklicznych, kopie konfiguracji, strażnicy działający spoza hostingu. Zobacz, co obejmuje opieka WordPress w Kosari.
Napisz do nas – sprawdzimy, czy Twoje automatyzacje naprawdę działają



