Wdrożenie Omnibusa w sklepie na WooCommerce (kurs)

Dziś będzie o CRONie, czyli harmonogramie zadań – ale nie takim systemowym, bo o nim już kiedyś pisałem, a CRONie zintegrowanym z WordPressem, czyli WP-CRON. Pewnie nawet sporo użytkowników tego CMSa nie wie, że tam gdzieś w tle działa jakiś CRON – ale to on odpowiada m.in. za sprawdzanie aktualizacji, czy publikację zaplanowanych wpisów. I właśnie w tym ostatnim kontekście (zaplanowane wpisy) często muszę tłumaczyć, że wszystko użytkownik ustawił dobrze, a wpis nie został opublikowany w zaplanowanym czasie bo… akurat nikogo nie było na stronie.

WordPress CRON (WP-CRON)

Nawet osoby, które wiedzą, że w WordPressie działa usługa WP-CRON (wykorzystywany m.in. przez wtyczki do kopii zapasowych, czy wysyłki newsletterów), i znają np. CRONa dostępnego np. w systemie Linux, często popełniają ten błąd, że traktują te 2 usługi w ten sam sposób, i jest to często źródłem późniejszych nieporozumień.

WP-CRON, prawie jak CRON

O ile obie usługi (CRON systemowy i WP-CRON) mają sporo wspólnych cech, obie służą do tego samego – wykonywania zdefiniowanych zadań w określonym czasie, to jednak WP-CRON do działania potrzebuje np. użytkowników odwiedzających naszą stronę.

Podczas takiej wizyty (w uproszczeniu, bez wdawania się w wyjątki) WordPress sprawdza, czy są jakieś zaplanowane zadania, które powinny zostać już wykonane, i jeśli są – wykonuje je.

Działa to całkiem nieźle na stronach z większym ruchem (pomijając ew. niepotrzebne obciążenie systemu, ale to raczej nie ma większego znaczenia dla funkcjonowania strony/serwera), gdzie co chwilę ktoś jest na stronie, i tym samym wzbudza WordPressa i usługę WP-CRON.

Zaplanowany post nie został opublikowany o czasie

Trochę gorzej sytuacja wygląda w przypadku stron z mniejszym ruchem, gdy brak odwiedzających sprawia, że usługa WP-CRON nie działa, a tym samym nie wykonują się żadne zaplanowane działania (np. publikacja zaplanowanego wpisu, kopia zapasowa, wysyłka newslettera).

By lepiej zobrazować „problem”, załóżmy, że naszą stronę odwiedza 12 osób dziennie, po jednej co pełną godzinę, od 8 rano, do 20 wieczorem. W tym czasie WP-CRON jest wzbudzany raz na godzinę (celowo pomijam ew. roboty indeksujące, czy SPAMboty).

I tak np. publikacja postu zaplanowana na godzinę 11:20 będzie miała miejsce dopiero o 12, bo wtedy na naszej stronie pojawi się kolejny użytkownik. I to najwcześniej.

Oczywiście jest to sytuacja celowo przerysowana, ale znam przypadki, gdy na stronie nie było nawet SPAMbota przez nawet kilka dni.

Kopia zapasowa rano zamiast w nocy

Ale spójrzmy na inny, bardziej prawdopodobny przykład – stronę odwiedza całkiem sporo użytkowników, ale prawdopodobnie większość tego ruchu skupia się między 6-7 rano, a 1-2 w nocy, czyli od godzin wczesnoporannych, po „późny wieczór”.

Z tego powodu kopię zapasową strony (BackUp) planuje się np. na 3-4 rano, tak by obciążenie serwera, które generuje to zadanie, nie wpływało na szybkość działania strony, gdy będą z niej korzystać użytkownicy (a zarazem takie puste godziny to jest dobry moment by „zamknąć dzień”, np. w przypadku sklepu internetowego).

Z racji tego, że na stronie o 3-4 często nikogo nie ma, to takie zadanie się nie wykona. Dopiero gdy na stronie zaczną pojawiać się pierwsi użytkownicy, zostanie wywołany WP-CRON, i wbrew założeniom kopia zapasowa zaczyna się ponad 2 godziny później, i to w momencie gdy na stronie zaczyna już przybywać użytkowników.

CRON systemowy zamiast WP-CRONa

Ja najczęściej – poza nielicznymi wyjątkami – by uniknąć takich sytuacji, jak i użytkowników/właścicieli stron, zaniepokojonych np. tym, że im się post nie opublikował (w pewnym sensie słusznie), wyłączam usługę automatycznego wykonywania usługi WP-CRON podczas odwiedzin na stronie, a zamiast tego korzystam z CRONa systemowego, który w zdefiniowanych odstępach czasu wywołuje usługę WP-CRON, dzięki czemu jej działanie nie jest zależne od odwiedzin na stronie.

Zaczynamy od wyłączenia usługi WP-CRON (może nie tyle całkowite wyłączenie, co bardziej wyłączenie automatycznego sprawdzania harmonogramu przy wywoływaniu strony) poprzez dodanie odpowiedniego wpisu w pliku wp-config.php, który znajduje się w głównym katalogu WordPressa:

define('DISABLE_WP_CRON', true);

Nie ma specjalnego znaczenia, w którym miejscu umieścicie ten wpis, choć dobrze zrobić to przed linijką:

/* To wszystko, zakończ edycję w tym miejscu! Miłego blogowania! */

Ew. w wersji angielskiej:

/* That's all, stop editing! Happy blogging. */

I to tyle – przynajmniej jeśli chodzi o wyłączeni usługi WP-CRON…

CRON systemowy uruchamia WP-CRON

By nie pozbawić się zadań cyklicznych/zaplanowanych w WordPressie musimy teraz sprawić, by raz na jakiś czas – zależnie od potrzeb – usługa WP-CRON startowała, by wykonać powierzone jej zadania.

W tym celu można wykorzystać CRON systemowy (Linux) np. na serwerze VPS (lub Raspberry Pi), w którym wystarczy dodać odpowiednie polecenie, by aktywować WP-CRON np. co 10 minut:

*/10 * * * * curl -s -o /dev/null http://strona1.webinsider.pl/wp-cron.php?doing_wp_cron > /dev/null 2>&1

Zamiast cURL można wykorzystać polecenie wget:

*/10 * * * * wget --delete-after -O -q -t 1 http://strona1.webinsider.pl/wp-cron.php?doing_wp_cron > /dev/null 2>&1

A jak strona znajduje się na tym samym serwerze, nawet bezpośrednie wywołanie pliku przez PHP:

*/10 * * * * php /var/www/strona1.webinsider.pl/public_html/wp-cron.php?doing_wp_cron

W tym przypadku można też skorzystać – sam zresztą preferuje to rozwiązanie – z narzędzia WP-CLI:

wp cron event run --due-now --path=var/www/strona1.webinsider.pl/public_html/

Wiele stron? Pomoże prosty skrypt

W przypadku, gdy chcecie w ten sposób obsłużyć więcej stron, to raczej nie ma sensu dodawać do CRONa każdej z nich – w tym celu lepiej posłużyć się prostym skryptem:

# !/bin/bash
curl -s -o /dev/null http://strona1.webinsider.pl/wp-cron.php?doing_wp_cron > /dev/null 2>&1
sleep 5
curl -s -o /dev/null http://strona2.webinsider.pl/wp-cron.php?doing_wp_cron > /dev/null 2>&1
sleep 5
# Strona z dodatkową autoryzacją HTTP: -u użytkownik:hasło
curl -s -o /dev/null http://strona3.webinsider.pl/wp-cron.php?doing_wp_cron -u użytkownik:hasło > /dev/null 2>&1

Lub gdy korzystamy z WP-CLI:

wp cron event run --due-now --path=var/www/strona1.webinsider.pl/public_html/ --quiet
wp cron event run --due-now --path=var/www/strona2.webinsider.pl/public_html/ --quiet
wp cron event run --due-now --path=var/www/strona3.webinsider.pl/public_html/ --quiet

Który oczywiście dodajmy do CRONa:

*/10 * * * * root /ścieżka/do/skryptu

Ale równie dobrze można do tego (uruchomienia usługi WP-CRON) wykorzystać jakieś narzędzie do monitorowania dostępności stron internetowych (np. Uptime Robot), czy nawet harmonogram dostępny w systemie Windows.

WP-CRON i czasowa blokada kolejnych uruchomień

Ale nawet jeśli nie planujecie „rezygnować” z użytkowników odwiedzających Waszą stronę jako „wyzwalaczy” usługi WP-CRON, to może zainteresuje Was opcja, dzięki której możecie ustawić blokadę wykonywania kolejnych wystąpień usługi przez zdefiniowany czas (od poprzedniego wystąpienia).

Wystarczy w pliku wp-config.php dodać linijkę:

define('WP_CRON_LOCK_TIMEOUT', 600);

W powyższym przypadku usługa WP-CRON nie będzie uruchamiana częściej niż co 10 minut (600 sekund).

(!) Zgłoś błąd na stronie
Pomogłem? To może postawisz mi wirtualną kawę?
LUTy dla D-Cinelike (DJI Mini 3 Pro, DJI Avata, OSMO Pocket) od MiniFly
Wdrożenie Omnibusa w sklepie na WooCommerce
Jak (legalnie) latać dronem w Kategorii Otwartej
Wdrożenie Omnibusa w sklepie na WooCommerce (kurs)
Patryk
Wdrożenie Omnibusa w sklepie na WooCommerce (kurs)