16. Cronjobs

Was ist ein Cronjob?

Wenn Sie schon einmal mit Linux oder einem Linux-ähnlichem System gearbeitet haben, kennen Sie die Cronjobs vielleicht bereits. Ein so genannter Cron-Daemon ist ein Hintergrunddienst, der dafür sorgt, dass Prozesse zeitbasiert ausgeführt werden können. Meist handelt es sich dabei um regelmäßig wiederkehrende Aufgaben, die man dann „Cronjobs“ nennt.

Hier ein kurzes Beispiel aus der Linux-Welt:


0	3	*	*	*	sh	/home/admin/mein-script.sh

Trägt man obiges in die Cronjob-Tabelle ein, wird jeden Morgen um 3 Uhr ein Shell-Script ausgeführt. Die ersten Zahlen und Sternchen (hier 0 3 * * * ) stellen ein Zeitintervall dar. Dahinter gibt man das auszuführende Programm und deren Parameter an.

Cronjobs in WordPress

Auch WordPress hat intern einen Pseudo-Cron-Daemon am laufen. Dieser funktioniert aber nicht wie sein Linux-Pendant. Denn das würde voraussetzen, dass mindestens ein PHP-Prozess im Hintergrund läuft der dann die einzelnen Cronjobs zum gewünschten Intervall triggert. Das ist jedoch nicht der Fall. Denn wie Sie sicherlich wissen, wird PHP nur dann ausgeführt, wenn es explizit aufgerufen wird. Entweder über einen Webserver oder über die Kommandozeile.

Deswegen geht man hier einen kleinen Umweg. Mit jedem Request, der an WordPress gesendet wird, wird überprüft, ob es Cronjobs gibt, die abgearbeitet werden müssen (wenn quasi das Zeitinterverall überschritten wurde). Falls ja, wird versucht, einen Aufruf an die Datei wp-cron.php zu senden. Möglichst so, dass das Rendering der aktuellen Seite nicht blockiert wird. In der angesprochenen Datei wird dann ein Cronjob „im Hintergrund“ ausgeführt. Zumindest so lange, bis die maximale Ausführungszeit von PHP erreicht ist. Diese kann je nach PHP-Konfiguration unterschiedlich sein.

Hier ein Beispiel: Nehmen wir an, wir registrieren eine PHP-Funktion als Cronjob in WordPress welcher alle 15 Minuten ausgeführt werden soll. Passiert das genau um Punkt 13 Uhr, würde man meinen, dass der Cronjob bis 14 Uhr genau vier mal gelaufen ist. Dem ist aber nicht so. Und zwar aus folgendem Grund:

Wenn wir eine relativ neue Seite betreiben, deren URL nur wir kennen, wird der erste Cronjob dann getriggert, wenn wir unsere eigene WordPress-Seite aufrufen. Nehmen wir an, das sei wieder um Punkt 13 Uhr. Der nächste Aufruf müsste dann um 13:15 Uhr stattfinden. Wenn wir bis dahin die Seite aber bereits verlassen haben und sich auch kein anderer Benutzer darauf tummelt, wird der Cronjob nicht aufgerufen. Stattdessen erst dann, wenn wir – oder ein anderer User – die Seite das nächste Mal aufruft. Das kann nach 15 Minuten aber genauso nach einer Woche passieren. Und der Cronjob ist dann, statt ein paar hundert Mal, tatsächlich nur zwei mal gelaufen.

Sie glauben, dass dieser Fall wohl eher die Ausnahme sei? Das stimmt so nicht. Fast jede größere Website nutzt mittlerweile ein Caching-Plugin. Liegt eine Seite erst einmal im Cache, wird sie ausgeliefert ohne dass PHP-Code ausgeführt wird. Das heißt auch, dass mit aktiviertem Caching-Plugin kein Cronjob ausgeführt wird. Oder eben nur dann, wenn wir selbst im Admin-Bereich eingeloggt sind und dadurch – durch einen Seitenaufruf – auch im Hintergrund die Datei wp-config.php aufgerufen wird.

Ganz besonders doof ist das natürlich, wenn wir die WordPress-Interne Funktion nutzen, die es uns erlaubt, Beiträge zeitgesteuert zu veröffentlichen. Genau das funktioniert dann nämlich nicht mehr oder nicht mehr richtig.

Richtige Cronjobs

Abhilfe für oben genannte Misere schafft nur ein richtiger Cronjob. Wenn wir bei Linux bleiben, könnte der in etwa so aussehen:


*/5	*	*	*	*	curl -so /dev/null https://meine-seite.com/wp-cron.php

Hier wird das Programm curl alle fünf Minuten aufgerufen. Es macht dann nichts anderes als die Datei wp-cron.php zu triggern und die Antwort des Aufrufs direkt zu löschen (Ausgabe nach /dev/null).

Etwas origineller geht das mit der WP-CLI. Ein Kommandozeilen-Tool für WordPress (http://wp-cli.org/):


*/5     *       *       *       *       wp cron event run --due-now --path=/var/www/meine-seite/ > /dev/null

In beiden Fällen ist es ratsam, folgende Zeile in der wp-config.php zu setzen:


define( 'DISABLE_WP_CRON', true );

Das bewirkt, dass kein Benutzer mehr einen Request über die Weboberfläche senden kann. Stattdessen klappt dass dann nur noch über den „richtigen“ Cronjob.

Hinweis
Wenn Sie die Möglichkeit haben, einen „richtigen“ Cronjob einzurichten, dann machen Sie davon gebrauch. Alles andere führt zu willkürlichem Verhalten.