Startseite → Leistungen → Automatisierte WordPress-Updates

Notizen aus der Umsetzung · WordPress-Wartung

Updates, die unbeaufsichtigt laufen.

Für eine niederländische Webagentur baue und betreue ich die WordPress-Websites ihrer Kunden. Updates von Core, Plugins und Themes liefen von Hand, Website für Website, und das begrenzte, wie oft sie überhaupt stattfinden konnten. Herausgekommen sind ein eigenes Wartungs-Plugin und ein Skript, das der Zeitplaner des Servers startet: Es aktualisiert, prüft danach, ob die Website noch funktioniert, und verschickt einen Bericht. Unten steht, was ich dabei gelernt habe — fast alles davon zeigte sich erst im Betrieb.

Server-Cron WP-CLI WooCommerce SSH MainWP SiteGround
Woher der Lauf kommt

Warum nicht WP-Cron.

WP-Cron startet, wenn jemand die Website besucht. Auf einer Website, die eine Woche lang niemand aufruft, bleiben geplante Aufgaben einfach still. Die Updates startet deshalb ein Eintrag im Zeitplaner des Hosters: ein PHP-Skript, das WordPress selbst lädt.

Damit wanderte das Problem nur woandershin. Außerhalb eines HTTP-Aufrufs ist das Array $_SERVER fast leer, also liefern Plugins mit typisierten Methoden daraus null und sterben an einem TypeError — während WordPress noch lädt, also bevor irgendetwas diesen Fehler in einen Bericht schreiben konnte. Das Skript füllt deshalb sichere Werte ein, bevor wp-load läuft.

Was diese Automatik nicht tut

Sie fasst wp-config.php nie an. Sie erkennt die Einstellungen darin, die man kennen sollte, und schreibt darüber, aber die Entscheidung bleibt bei einem Menschen: In dieser Datei stehen eigene Konstanten, und ein Tippfehler legt die Website lahm.

Sie nimmt ein Update auch nicht von selbst zurück — der Bericht nennt die Versionen vorher und nachher, es gibt also einen Punkt, zu dem man zurückkehren kann. Und eine Korrektur für eine einzelne Website bleibt auf deren Server, mit Backup und Notiz; sie wandert nicht in den Code, der an alle ausgeliefert wird.

Was kaputtging

Vier Dinge, die überarbeitet werden mussten.

Eine Ausnahmeliste, die nicht abdeckte, wofür sie gedacht war

Manches sollte eine Automatik nicht aktualisieren. Die Ausnahmeliste entstand, nachdem ein Bricks-Update eine Website für einen halben Tag lahmgelegt hatte. Die Ursache: 2.4 ruft die Hooks der Vorlagen über do_action_ref_array() auf, und WordPress ergänzt fehlende Argumente nur bei do_action() — die Callbacks des Child-Themes mit einem erforderlichen Parameter starben also an einem ArgumentCountError. Bei einem manuellen Lauf auf derselben Website aktualisierte die Automatik Bricks trotzdem, obwohl es auf der Liste stand: Die Liste wurde nur bei Plugins geprüft, und Bricks installiert sich als Theme.

Der zweite Fund in derselben Woche: Das Speichern eines Einstellungs-Tabs setzte die Liste auf leer zurück. Die Speicherroutine verarbeitet nur Felder des eigenen Tabs, und die Zuweisung war im Block eines anderen Tabs gelandet — bei jedem Speichern ging der Wert auf ''. Beides zu beheben war die Bedingung dafür, vom wöchentlichen auf einen täglichen Lauf umzustellen.

Die Testbestellung, die Shopbetreibern E-Mails schrieb

Nach einem Update muss ein Shop geprüft werden, denn eine kaputte Kasse meldet sich nicht von selbst. Die erste Fassung legte eine Testbestellung an und räumte hinter sich auf — sie setzte den Status auf „storniert" und verschob die Bestellung in den Papierkorb. Der Status „storniert" löst die eigene E-Mail von WooCommerce aus, und der Papierkorb versteckt die Bestellung: Shopbetreiber bekamen Post über eine stornierte Bestellung, die sie nicht finden konnten. Filter helfen nicht, weil diese Mail aus einer Warteschlange im nächsten Aufruf hinausgeht. Das Aufräumen wechselte also zum endgültigen Löschen — das auf Shops mit den neuen Bestelltabellen gar nichts löschte, weil Bestellungen dort nicht mehr bei den Beiträgen liegen.

Heute legt die Automatik keine Bestellung an. Sie geht den Shop so durch wie eine Kundin — Startseite, Produktseite, Warenkorb über die Store API, Kassenseite — und hält vor der Zahlungsschaltfläche an. In Shops mit Schnittstellen weckt eine neue Bestellung innerhalb von Sekunden die Buchhaltung und das Mailsystem, und manche vergeben schon beim Anlegen eine Rechnungsnummer.

Ein Alarm, der jeden Tag losgeht, ist kein Alarm mehr

Die Dateien von Core und Plugins werden mit den Prüfsummen von wordpress.org verglichen. Sie meldeten zu viel: Der Hoster schreibt php_errorlog in das Verzeichnis, aus dem das fehlgeschlagene Skript lief — auch tief im Core; eine Website hat eine alte .htaccess im Core, die den Zugriff sperrt und sonst nichts tut; auf einer anderen hat eine Migration vor Jahren die Zeilenenden in Dutzenden Dateien geändert. Jeder dieser Fälle bekam eine eigene Regel statt einer Ausnahme für ein ganzes Plugin. Dateien, die der Scanner des Hosters bereits in Quarantäne verschoben hat, werden getrennt gemeldet.

Die andere Richtung war schlimmer. Wenn das Werkzeug nichts zurückgab, fiel die leere Liste der Unterschiede in den Zweig „keine Änderungen" — eine fehlgeschlagene Prüfung wurde also als sauberes Ergebnis gemeldet. „Konnte nicht geprüft werden" ist heute ein eigener Zustand.

Eine Version, die nur aussah wie installiert

Das Cron-Skript liegt im WordPress-Verzeichnis, und das Plugin kopiert es selbst dorthin. Es tat das beim Update-Ereignis des Plugins und dann, wenn eine angemeldete Administratorin das Dashboard öffnete — eine Masseninstallation über MainWP oder eine Kopie per SFTP löst beides nicht aus. Das Dashboard zeigte die neue Version, der nächtliche Lauf führte Code von vielen Versionen vorher aus, und nirgends stand etwas davon. Heute wird die Version bei jedem Lauf verglichen und zusätzlich bei einem gewöhnlichen Besuch der Website, ohne dass jemand angemeldet ist.

Legen wir los

Updates bleiben liegen, weil niemand die Website danach prüfen kann?

Schreiben Sie, wie viele Websites es sind und ob Shops dabei sind. Ich sage Ihnen, was sich gefahrlos nach Zeitplan erledigen lässt und was weiterhin von Hand gemacht werden muss.

Ihre Websites beschreiben →

Oder per E-Mail: info@asymetria.com.pl