Cron on sisäinen kello, Halutun ajan jälkeen se tekee jotain. Usein se ajaa jonkun PHP-koodin tai jotain muuta vastaavaa. WordPress on hyvin riippuvainen cronista. Kaikki ajastetut tehtävät, kuten kalenterissa olevat julkaisujonot, päivitykset ja tietokannan siivoukset riippuvat cronista. WordPressissä se on ratkaisu sisäisellä cron-skriptillä, joka käynnistyy aina kun joku tulee sivustolle. Ja tässä piileekin ongelma. Jos tulee paljon liikennettä, niin se käynnistyy koko ajan. Jos ketään ei tule, niin mitään ei tehdä. Entä jos välissä on Varnish ja vaikka kävijöitä onkin, niin he saavat sisällön välimuistista eikä Apachella majaileva WordPressin cron tiedä siitä mitään. Tarvitaan siis erillinen cron.
Lähtökohta on siis WordPressin oman cronin epäluotettavuus:
- ruuhka-aikana se kuormittaa toimiessaan koko ajan
- hiljaisena aikana se ei toimi ollenkaan
WordPressin oman cronin sammuttaminen
Onneksi jokaisessa linuxissa on oma cron, myös Ubuntussa. Sitä on syytä käyttää. Jotta saataisiin tasaisesti tikittävä kello, joka käynnistää tehtävät silloin kun kuuluu, eikä silloin kun joku sattuu piipahtamaan sivustolla, niin ensimmäiseksi täytyy sammuttaa WordPressin oma cron.
Teen kaiken root-tunnuksella. Se on paljon helpompaa. Joten jos sinä et, niin muista sudo
tai su
. Polut ja osoitteet ovat esimerkkejä ja sinun täytyy muuttaa ne itsellesi sopiviksi.
Avataan wp-config.php
:
nano /var/www/html/wp-config.php
Lisää tämä johonkin kohtaan, vaikka alkuun:
define('DISABLE_WP_CRON', true);
Kun olet tallentanut, niin WordPressin oma cron on pysähtynyt ja aivan riippumatta käykö miljoona ihmistä vai onko täysin autioita, niin sitä ei käynnistä yhtään mikään. Siksi täytyy säätää Ubuntun omaa cronia, jotta se liipaisisi WordPressin ajastetut toiminnot käyntiin – eli käyttäytyy WordPressin mielestä kuin joku tulisi käymään.
Ubuntu ja cron
Tarkoitus on käyttää systeemin omaa cronia, joka saadaan tekemään ajastetusti (melkein) mitä tahansa. WordPressin ajastettujen toimintojen käynnistäminen on vain yksi tehtävä monien muiden mahdollisten joukossa.
Jokaisella käyttäjällä on croninsa. Hän voi silloin ajastella omia juttujaan miten haluaa, eikä se liity muihin. Ja tähän minä olen kompastunut. Se nimittäin koskee myös tiedostojen ja hakemistojen omistajuutta.
Webhakemisto on Apachen (tai mikä webpalvelimena pyöriikään) ikioma. Sen takia sen omistajaksi on asennettu www-data
, joka on webpalvelimen toinen nimi Ubuntussa ja Debianissa. Muissa linuxeissa se on jotain muuta. Ongelma on siinä, että kokeilen aika ajoin kaikennäköistä. Siirtelen tiedostoja FTP:llä tai asentelen sekä säädän rootina. Ja silloin omistajuus aina muuttuu rootille.
Kun cronin omistaa www-data
, niin se toimii niin kauan, kunnes olen tehnyt jotain ja yhtä äkkiä wordpress-hakemisto onkin rootin nimissä. Silloin muut käyttäjät, kuten vaikka www-data
, ei saa tehdä siellä miten ja samaan kuuluu käyttäjän omistama cron. Saattaa mennä pitkäänkin, ennenkuin oivallan, että jokin ei ole kunnossa. Yleensä se tulee silloin kun alan ihmetellä, että eikö varmuuskopiointia olekaan tehty tai asiakkaat huutelevat saamattomien sähköpostien perään. Apachen oma cron on asetettu, mutta se ei tee mitään.
WordPress ja cron
Cronin asettaminen WordPressin käyttöön on helppoa. Teen sen esimerkissä Apachelle, mutta jos se lakkaa toimimasta, niin tee cron uudestaan ja sillä kertaa laita käyttäjäksi root.
crontab -u www-data -e
Valitsimen -u
jälkeen annetaan käyttäjä ja -e
tarkoittaa muokkaamista. Jos tämä oli ensimmäinen kerta, kun käynnistät crontabin, niin se kysyy sinulta mitä editoria haluat käyttää. Valitse mieluinen, itse tyydyn nanoon.
Skrollaa alas asti.
Liitä tämä viimeiselle riville:
*/1 * * * * curl --silent https://www.example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Itse en käytä curlia, vaan annan PHP:n hoitaa työn. Minulle ei ole tuohon mitään järjellistä syytä, vaan ainoastaan säikkyminen Varnishin ja cachen vaikutuksesta, sillä curl urlin kanssa keskustelee välimuistin kanssa. PHP toimii suoraan taustalla.
*/1 * * * * php -q /var/www/example.com/public_html/wp-cron.php >/dev/null 2>&1
Jos sinulla on asennettuna WP CLI, niin voit käyttää sitä käynnistämässä WordPressin ajastettuja toimintoja.
*/1 * * * * cd /var/www/html/; /usr/local/bin/wp cron event run --due-now >/dev/null 2>&1
Alussa olevat tähdet merkitsevä aikaa. Googleta lisää cronista, jos olet utelias, mutta tuo käynnistyy kerran minuutissa. Ehkä hieman turhan usein minun käytössäni, mutta parempi sekin kuin 100 kertaa sekunnissa tai ei kertaakaan yöllä, jolloin backupit pitäisi ajaa. Vaikka kerran minuutissa saattaa tuntua tiheältä, niin ei se ole. Eikä se kuormita.
Kerran minuutissa järjestelmä käy tökkäisemässä sivustolla WordPressin cronia ja herättää sen töihin. Se siis eräällä tavalla fuskaa olevansa kävijä. /dev/null
on roskis, eli ilmoituksia tuosta ei tule.
Tallenna ja sinulla on cron päällä.
Osa plugineista on sitten suunnattoman huolissaan ja kokevat velvollisuudekseen kertoa sinulle koko ajan, että cron ei ole päällä. On se, ne eivät vain tiedä sitä, koska kurkkivat vain wp-config.php
-tiedostosta onko WordPressin oma cron estetty.
Varnish, WP Rocket ja välimuisti
Varnish saattaa olla kiusa. Samaten WordPressin omat välimuistiohjelmat. Ne saattavat tehdä kopion wp-cron.php
:stä, koska niiden mielestä se on käyty sivu siinä kuin muutkin. Lisäksi ?-merkin jälkeiset siivotaan pois, koska ne eivät ole oleellisia – paitsi, että tällä kertaa se kertoo wp-cron.php
:lle mitä sen pitäisi tehdä.
WP Rocket on helppo ja jos käytät varokaa-halpoja-kopioita kuten WP Super Cacheä, W3 Total Cachea tai jotain muuta noin kiljuunasta välimuistittajasta, joille yliraskaiksi paisuneet teemat petaavat tietä, niin niissä on vastaava asetus. Jossain.
WP Rocketin asetusten välilehti Lisäasetukset
ja heti ensimmäinen kohta Välimuistista pois suljettavat URL-osoitteet
. Laita laatikkoon:
/wp-cron.php
Tuo saattaa olla liioittelua, mutta onpahan kuitenkin.
Varnish saattaa vaatia hieman säätöä. Tosin, jos sinulla on jo käytössä WordPressin huomioiva .vcl
, niin asia pitäisi olla kunnossa. Tarkistetaan se. Avaa default.vcl
:
nano /etc/varnish/default.vcl
Sinulta pitäisi löytyä osiosta vcl_recv
aivan tai lähes alusta tämä tai vastaava:
# Fix WordPress visual editor issues, must be the first one of return(..) statements to work if (req.url ~ "/wp-(login|admin|comments-post.php|cron)" || req.url ~ "preview=true" || req.url ~ "xmlrpc.php") { return(pass); }
WordPress Multisite ja cron
Äsken kerrottu cron toimii normaalissa WordPressissä, mutta ei Multisite-asennuksessa. Kun kerran minuutissa piipahdettiin osoitteessa www.example.com
, niin se ei näpäytä cronia osoitteissa sub.example.com
tai www.example.com/sub
– eli aivan riippumatta onko multisite asennettuna alidomaineihin tai hakemistoihin. Ja kun WordPressin oma cron on suljettu, niin noita kahta ei kukaan koputtele.
Jos annetaan periksi ja sallitaan WordPressin cron, niin tilanne on se, että yhdellä saitilla saattaa olla tolkuton ruuhka ja sen cron tikittää samaa hommaa elämänsä hädässä. Edelleenkään sinne alidomainissa tai hakemistossa sijaitsevaan rauhallisempaan WordPressiin ei tule ketään – eikä niiden elämää liikauta mikään. Niiden suhteen mikään ei siis muuttunut.
Mutta ratkaisu on aivan yhtä helppo. Lisätään rivi per multisiten asennus. Joten avataan taas crontab
:
crontab -u www-data -e
Lisää loppuun tarvittava määrä sivustoja esimerkin mukaan (tai jollain muulla haluamallasi syntaksilla):
*/1 * * * * curl --silent https://www.example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1 */1 * * * * curl --silent https://www.example.com/sub/wp-cron.php?doing_wp_cron >/dev/null 2>&1 */1 * * * * curl --silent https://sub.example.com/wp-cron.php?doing_wp_cron >/dev/null 2>&1
Tallenna ja homma on hoidossa.
Tuo toimii pienemmillä asennuksilla. Kuten jos pyörittää oman sivuston kieliversioita tai vastaavia. Mutta jos sivustoja sata tai tuhat, tai kävijät voivat rekisteröidä omia sivustojaan, niin moinen ratkaisu ei enää silloin toimi. Käsin lisääminen ei ole vaihtoehto moisessa tilanteessa, vaan cron täytyy asettua automaagisesti.
Tarvitaan PHP-pohjaisia ratkaisuja, joka hakee dynaamisesti tiedot ”cronattavista” sivustoista. Niistä löytyy esimerkkejä valmiiden PHP-tiedostojen kanssa, kun googletat.
Cronin seuraaminen
Tieto siitä, että toimiiko cron pitäisi saada hieman helpommaksi kuin arvuuttelu puuttuvista backupeista.
Yksi on cronin itsensä käyttö, jos serveri osaa lähettää sähköpostia. Lisää tämä ihan ensimmäiseksi cronin alkuun:
MAILTO=email@example.com
Se asettaa cronille muuttujaksi sähköpostiosoitteen, johon lähetetään aina mailia cronin suorittamisesta, jos sitä ei ole erikseen estetty >dev/null
tai rajoittamalla mailin lähtö vain virhetilanteeseen.
Lisää tämä cronin loppuun:
0 8 * * * curl --silent https://www.example.com/wp-cron.php?doing_wp_cron 2>&1 0 8 * * * curl --silent https://www.example.com/wp-cron.php?doing_wp_cron
Tuo ei tee sen kummallisempaa kuin ajaa joka päivä kello 8.00 saman WordPressin cronin kuin mikä ylipäätään ajetaan kerran minuutissa. Ensimmäinen lähettää sähköpostin, jos on virhetilanne. Toinen on hieman kertausta, mutta se lähettää mailin, kun cron on suoritettu. Kyse on ehkä turhasta varmistelusta, mutta jos kakkosmailia ei tule, niin rootin cronia ei ole ajettu jostain syystä.
En tee tuota jokaiselle Multisiten asennukselle erikseen, yksi saa riittää. Rajansa se on huolellisuudellakin.
Toki mailin voisi pyytää virhetilanteessa siinä ”varsinaisessakin”, jonka ilmoitukset ohjataan nyt Suureen Tuntemattomaan >dev/null
avulla. Se vaan täyttää hyvin äkkiä postilaatikon, koska virhetilanteessa lähettäisi postia joka hemmetin minuutti.
Joskus on ihan vaan kiva vilkaista WordPressissä onko kaikki cronin ajastamat ajettu. Se hoituu pluginilla. Asenna tämä:
https://fi.wordpress.org/plugins/wp-crontrol/
Löydät WordPressin Työkalut hakemistosta uuden kohdan Cron events. Jos siinä kerran minuutissa ajettavissa on suunnilleen sama kellonaika kuin mitä virallinen aika sillä hetkellä on, niin kaikki toimii. Jos se on enemmän jäljessä, niin jostain syytä cron ei toimi. Onnea vaan virheen etsimiselle silloin.
Mutta näppärin tapa tarkistaa cron on käyttää WP CLI:tä. Komento on yksinkertainen:
wp cron event list
Saat vastaukseksi jotain tällaista:
Vilkaiset, että onko edellinen ajokerta ollut jotakuinkin järjellisessä ajassa. Muista, että aika on GMT eli lisää siihen 2 tuntia (tai 3 kesäaikana).