WordPress wp-cron uitschakelen en system cron gebruiken
WP-Cron draait alleen bij paginabezoek, wat zorgt voor vertraging of overbelasting. Schakel dit uit en gebruik WP-CLI met een system cron voor betrouwbare taakuitvoering.
Wat wp-cron is en waarom system cron dit vervangt
WP-Cron is de ingebouwde taakplanner van WordPress die alleen wordt uitgevoerd wanneer iemand een pagina opvraagt. Niets binnen WordPress wordt uit zichzelf actief. Bij elk verzoek dat niet vanuit een cache wordt geserveerd, leest WordPress een lijst met geplande taken. Als er een taak moet worden uitgevoerd, stuurt WordPress een tweede HTTP-verzoek naar zichzelf op /wp-cron.php om het werk te verrichten. Door deze taak te verplaatsen naar system cron, krijgt u één voorspelbare uitvoering op een vast schema, ongeacht of de site op dat moment duizend bezoekers heeft of geen enkele.
Twee regels voeren het eigenlijke werk uit: een constante in wp-config.php en een crontab-item. Al het overige in deze handleiding betreft de zaken die deze twee regels niet vermelden. Onder welke gebruiker de taak moet worden uitgevoerd, hoe u bewijst dat de geplande gebeurtenissen daadwerkelijk zijn gestart en de drie manieren waarop de configuratie kan falen zonder dat er iets op de site wordt weergegeven.
De voorbeelden gebruiken /srv/www/example.com als de WordPress-directory en www-data als de webservergebruiker. Vervang overal uw eigen paden en gebruiker.
Welke bezoeker veroorzaakt cron-kosten op een drukke site
Elk verzoek dat niet uit de cache komt, betaalt voor de controle. WordPress laadt de cron optie, vergelijkt tijdstempels en wanneer er een taak klaarstaat, roept het spawn_cron() aan, dat een niet-blokkerend loopback-verzoek naar /wp-cron.php stuurt. De bezoeker wacht niet op het resultaat. Een PHP-worker doet dat wel. Op een kleine VPS die PHP-FPM draait met pm.max_children = 5, houdt één trage geplande taak een vijfde van uw PHP-capaciteit bezet zolang als nodig is, en de kans is het grootst dat dit wordt geactiveerd tijdens uw drukste minuut, omdat er dan de meeste pagina's worden geladen.
WordPress beperkt duplicaten wel. Het neemt een lock met een levensduur van WP_CRON_LOCK_TIMEOUT, standaard 60 seconden, zodat gelijktijdige bezoekers niet elk een run starten. De lock beperkt duplicatie. Het verplaatst het werk niet buiten het verzoekpad.
Tel hoe vaak het op uw eigen server wordt geactiveerd voordat u beslist of het relevant is. Elke loopback verschijnt in het toegangslogboek van de webserver:
sudo grep -c 'wp-cron.php' /var/log/nginx/access.logApache schrijft in plaats daarvan naar /var/log/apache2/access.log. Een aantal van duizenden per dag is een reële kostenpost, en het is het soort getal dat u op uw eigen machine moet meten in plaats van in een artikel te lezen, op dezelfde manier als u een VPS zou benchmarken voor en na elke andere wijziging.
Caching verandert het beeld. Als een paginacache de meeste verzoeken als statische HTML serveert, draait PHP nooit voor die verzoeken, waardoor de cron-controle nooit plaatsvindt. Een zwaar gecachte drukke site begint zich te gedragen als de rustige site hieronder.
Waarom bezoekersafhankelijke cron niet werkt op een rustige site
Geen bezoekers betekent geen cron. Een site die slechts enkele bezoeken per dag ontvangt, voert zijn geplande taken slechts enkele keren per dag uit, op de willekeurige momenten dat die bezoeken plaatsvinden.
De symptomen vertonen allemaal hetzelfde patroon. Een bericht dat voor 09:00 is ingepland, blijft in de berichtenlijst staan met de status Missed schedule totdat iemand een pagina laadt. Back-upplugins slaan de nacht over. Updatecontroles lopen achter, waardoor het dashboard geen updates toont terwijl er al een beveiligingsrelease beschikbaar is. Bestelmails, verlengingsberichten en waarschuwingen voor verloopdata worden te laat verzonden.
Niets hiervan genereert een foutmelding in de logs. De taak was volgens WordPress nooit te laat, omdat deze simpelweg nooit is gestart.
Stap 1: de visitor trigger uitschakelen in wp-config.php
Open /srv/www/example.com/wp-config.php en voeg de constante toe:
define( 'DISABLE_WP_CRON', true );Plaats deze boven de regel met /* That's all, stop editing! Happy publishing. */, omdat de regel direct onder dat commentaar wp-settings.php vereist, en wp-settings.php de plek is waar WordPress de cron-check aan init koppelt. Een constante die na die require wordt gedefinieerd, is te laat ingesteld om nog effect te hebben; het bestand ziet er dan correct uit terwijl de trigger blijft draaien.
Controleer of de regel op de juiste plek staat:
grep -n "DISABLE_WP_CRON\|stop editing" /srv/www/example.com/wp-config.phpDe constante voorkomt niet dat taken worden ingepland. Plugins blijven taken aan de wachtrij toevoegen, precies zoals voorheen. Het voorkomt alleen dat paginaladingen die wachtrij uitvoeren, wat betekent dat de wachtrij nooit wordt verwerkt totdat u stap 3 voltooit.
Het blokkeert ook geen directe verzoeken aan /wp-cron.php. Iedereen kan die URL nog steeds aanroepen, wat meestal ongevaarlijk is omdat het bestand alleen taken uitvoert die op dat moment gepland staan. Het blokkeren hiervan in uw webserverconfiguratie is optioneel. Als u dit wel blokkeert, werkt de curl-fallback aan het einde van deze handleiding ook niet meer.
Stap 2: WP-CLI installeren
WP-CLI is de officiële command-line tool voor WordPress. Deze vereist de PHP command-line binary, wat een apart pakket is van de PHP-module voor de webserver.
php -v
sudo apt install -y php-cliInstalleer WP-CLI vanaf de phar-build, zoals aanbevolen in de officiële installatiehandleiding:
cd /tmp
curl -O https://raw.githubusercontent.com/wp-cli/builds/gh-pages/phar/wp-cli.phar
php wp-cli.phar --info
chmod +x wp-cli.phar
sudo mv wp-cli.phar /usr/local/bin/wp
wp --infophp wp-cli.phar --info toont het pad naar de PHP-binary, de PHP-versie en de WP-CLI-versie. Als alle drie worden weergegeven, werkt de phar correct. Sinds augustus 2026 hanteert de installatiehandleiding PHP 7.2.24 als minimumvereiste. Aangezien Ubuntu 24.04 standaard PHP 8.3 bevat, voldoet een actuele server ruimschoots aan deze eis. Voer updates later uit met sudo wp cli update.
Voer WP-CLI uit als de gebruiker van de site, nooit als root:
sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com core versionAls root weigert WP-CLI te starten:
Error: YIKES! It looks like you're running this as root.Het systeem suggereert --allow-root. Gebruik dit hier niet. De reden hiervoor wordt uitgelegd in de eerste foutmodus hieronder.
Let er ook op dat sudo -u www-data -i niet werkt, omdat de login-shell van dat account /usr/sbin/nologin is en u de melding This account is currently not available. krijgt. Door het commando direct door te geven aan sudo -u wordt de login-shell overgeslagen, waardoor het commando correct wordt uitgevoerd.
Controleer nu of WordPress de constante uit stap 1 herkent:
sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com eval 'var_dump( DISABLE_WP_CRON );'Dit geeft bool(true) weer. Een fatale foutmelding over een niet-gedefinieerde constante betekent dat de regel define() niet wordt bereikt; dit duidt er meestal op dat de regel onder de require-instructie is geplaatst.
Stap 3: voeg de cron-taak toe als de juiste gebruiker
De juiste gebruiker is de eigenaar van de bestanden waar PHP naar schrijft. Controleer beide kanten:
stat -c '%U %G' /srv/www/example.com/wp-content/uploads
grep -E '^(user|group) = ' /etc/php/8.3/fpm/pool.d/www.confOp een standaard Ubuntu-installatie is het antwoord in beide gevallen www-data. Als u de site een eigen PHP-FPM-pool met een eigen gebruiker hebt gegeven, wat meestal het eindpunt is van een per-site configuratie op een LAMP-stack op Ubuntu 24.04, gebruik dan die gebruiker voor alle onderstaande stappen.
Maak een logdirectory aan waar die gebruiker naar kan schrijven:
sudo install -d -o www-data -g www-data -m 750 /var/log/wp-cronBewerk de crontab van die gebruiker:
sudo crontab -u www-data -eVoeg één regel toe:
*/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-example.lock /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now >> /var/log/wp-cron/example.log 2>&1Stap voor stap. */5 voert het elke vijf minuten uit. flock -n gebruikt een lock-bestand en stopt direct als een vorige uitvoering nog actief is. /usr/local/bin/wp is het absolute pad, wat cron vereist. --path zorgt ervoor dat het commando vanuit elke werkdirectory kan draaien. --due-now voert alleen de events uit waarvan de tijd is aangebroken, in plaats van elk event in de wachtrij. De redirect stuurt normale uitvoer en foutmeldingen naar één bestand dat u kunt inzien.
Die redirect is in de praktijk niet optioneel. Cron mailt de uitvoer van een taak naar de gebruiker, de meeste VPS-images hebben geen mail transfer agent geïnstalleerd, en cron logt vervolgens (CRON) info (No MTA installed, discarding output) en gooit de uitvoer weg. Een bestand bewaart het bewijs.
Controleer of het bestand is opgeslagen:
sudo crontab -u www-data -lGebruik voor meerdere sites per regel een verspringende minuut, zodat ze niet allemaal tegelijk starten:
*/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-one.lock /usr/local/bin/wp --path=/srv/www/one.example.com cron event run --due-now >> /var/log/wp-cron/one.log 2>&1
2-59/5 * * * * /usr/bin/flock -n /run/lock/wp-cron-two.lock /usr/local/bin/wp --path=/srv/www/two.example.com cron event run --due-now >> /var/log/wp-cron/two.log 2>&1Het logbestand groeit oneindig tenzij u het roteert. Schrijf /etc/logrotate.d/wp-cron:
/var/log/wp-cron/*.log {
weekly
rotate 4
missingok
notifempty
compress
create 640 www-data www-data
}Controleer of het bestand correct wordt geparseerd zonder wijzigingen door te voeren: sudo logrotate --debug /etc/logrotate.d/wp-cron.
Stap 4: bevestig dat de geplande events daadwerkelijk zijn uitgevoerd
Een crontab-regel die succesvol is opgeslagen, bewijst niets. Werk van de eenvoudigste controle naar de controle die uitsluitsel geeft.
Controleer eerst of cron het commando heeft gestart. Cron logt naar de journal onder zijn eigen unit:
journalctl -u cron.service --since "15 min ago" | grep wpEen gezonde vermelding ziet er als volgt uit, waarbij de tijdstempel en hostnaam aan het begin zijn weggelaten:
CRON[24913]: (www-data) CMD (/usr/bin/flock -n /run/lock/wp-cron-example.lock /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now >> /var/log/wp-cron/example.log 2>&1)Deze regel betekent dat cron uw commando heeft gestart als www-data. Het zegt niets over de vraag of het commando ook daadwerkelijk heeft gewerkt.
Controleer ten tweede of WordPress iets heeft uitgevoerd. Lees het logbestand:
sudo tail -n 20 /var/log/wp-cron/example.logWP-CLI print één regel per event, gevolgd door een totaal:
Executed the cron event 'wp_version_check' in 0.418s.
Success: Executed a total of 2 cron events.Fouten komen in hetzelfde bestand terecht, wat precies het doel is van 2>&1. Bij de meeste runs is er niets gepland en wordt er weinig geschreven; lees het bestand daarom na een run waarvan u weet dat er werk klaarstond.
Bewijs ten derde de werking van begin tot eind. Plan een markeringsevent en kijk of deze verdwijnt:
sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event schedule wp_cli_cron_check now
sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event list --fields=hook,next_run_relative --format=csv | grep wp_cli_cron_checkWacht één interval en voer het lijst-commando opnieuw uit. De hook is verdwenen, omdat een eenmalig event uit de wachtrij wordt verwijderd zodra het wordt uitgevoerd. Geen enkele plugin registreert een callback op die hook-naam, dus het uitvoeren ervan heeft verder geen effect op de site. Als de hook na twee intervallen nog steeds in de lijst staat, wordt de wachtrij niet verwerkt. De eerste twee controles vertellen u vervolgens of het probleem bij cron of bij WP-CLI ligt.
Gebruik hiervoor niet wp cron test. Dat commando controleert of het door bezoekers getriggerde spawnen werkt, en het geeft een foutmelding wanneer DISABLE_WP_CRON op true staat. Op een correct geconfigureerde server is die foutmelding de verwachte output, geen defect.
Het alternatief met systemd timers
Als de rest van de geplande taken op de server al draaien als systemd services en timers, breng WordPress dan ook daar onder. Elke uitvoering verschijnt dan in systemctl list-timers en de output gaat naar de journal in plaats van naar een bestand dat u moet roteren.
Maak /etc/systemd/system/wp-cron-example.service aan:
[Unit]
Description=Run due WordPress cron events for example.com
[Service]
Type=oneshot
User=www-data
Group=www-data
ExecStart=/usr/local/bin/wp --path=/srv/www/example.com cron event run --due-nowVervolgens /etc/systemd/system/wp-cron-example.timer:
[Unit]
Description=Run WordPress cron for example.com every 5 minutes
[Timer]
OnCalendar=*:0/5
AccuracySec=30s
Persistent=true
[Install]
WantedBy=timers.targetsudo systemctl daemon-reload
sudo systemctl enable --now wp-cron-example.timer
systemctl list-timers wp-cron-example.timer
journalctl -u wp-cron-example.service -n 20Systemd voert niet twee kopieën van dezelfde service tegelijk uit, dus deze versie heeft flock niet nodig. Persistent=true zorgt ervoor dat een taak wordt ingehaald als deze is gemist terwijl de machine uitstond; dit is iets wat een crontab-item niet kan.
Kies voor de crontab of de timer. Als u beide tegelijk op dezelfde site uitvoert, wordt de wachtrij dubbel verwerkt en zijn dubbele uitvoeringen van e-mail- of besteltaken zichtbaar voor uw klanten.
Waarom de cron job niet als root mag draaien
Dit is de eerste van de drie manieren waarop de configuratie kan falen. Plaats de taak in de crontab van root en WP-CLI stopt voordat er enige actie wordt ondernomen:
Error: YIKES! It looks like you're running this as root.De wachtrij wordt nooit verwerkt en als u de output niet heeft omgeleid, ziet u het bericht nooit. De gevaarlijke oplossing is het toevoegen van --allow-root, omdat elk bestand dat een plugin tijdens die run schrijft daarna eigendom is van root. Het volgende webverzoek draait als www-data, kan niet naar die mappen schrijven en de site begint meldingen te geven zoals:
Unable to create directory wp-content/uploads/2026/08. Is its parent directory writable by the server?Herstel het eigenaarschap en verplaats de taak vervolgens:
sudo chown -R www-data:www-data /srv/www/example.com/wp-contentDe crontab van root en de crontab van www-data zijn afzonderlijke bestanden, dus het verwijderen van de regel uit de ene heeft geen invloed op de andere. Controleer beide:
sudo crontab -u root -l
sudo crontab -u www-data -lWaarom cron wp: not found rapporteert
Dit is de tweede fout. Cron geeft taken van gebruikers een zeer beperkt PATH, /usr/bin:/bin. WP-CLI wordt geïnstalleerd in /usr/local/bin, wat niet in die lijst staat. De taak start, faalt binnen een fractie van een seconde en het logbestand bevat één regel:
/bin/sh: 1: wp: not foundBekijk de omgeving van cron zelf in plaats van te gissen. Voeg een tijdelijke regel toe:
*/5 * * * * env > /tmp/cron-env.txt 2>&1Lees /tmp/cron-env.txt na één interval en verwijder daarna de regel. De waarde PATH= in dat bestand is exact wat uw taak ontvangt.
Er zijn twee oplossingen. Gebruik het absolute pad /usr/local/bin/wp, zoals in stap 3. Of stel het PATH eenmalig in bovenaan de crontab, boven elke taakregel:
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/binDezelfde valkuil bevindt zich één niveau lager. Het wp phar-bestand begint met #!/usr/bin/env php, dus de shell moet ook php kunnen vinden. Als PHP zich buiten /usr/bin bevindt, wat gebeurt bij aangepaste builds en builds van controlepanelen, krijgt u:
/usr/bin/env: 'php': No such file or directoryRoep in dat geval de interpreter expliciet aan, bijvoorbeeld /usr/local/bin/php /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-now.
Waarom een interval van één minuut het oorspronkelijke probleem opnieuw veroorzaakt
Dit is de derde keer dat het misgaat. * * * * * voelt veiliger dan vijf minuten, maar op een drukke site brengt het u terug bij af. Als één uitvoering langer duurt dan het interval, start de volgende uitvoering terwijl de eerste nog bezig is. Tien minuten later zijn er tien PHP-processen actief, die elk hun eigen geheugen en databaseverbinding vasthouden.
Controleer direct op een opstapeling:
ps -eo etimes,user,args | grep '[c]ron event run'etimes is de leeftijd van het proces in seconden. Eén regel is gezond. Meerdere regels met leeftijden die ver boven uw interval liggen, betekenen dat uitvoeringen zich opstapelen. Op een kleine VPS eindigt dit in een MySQL Too many connections-fout, of in de kernel die PHP beëindigt om geheugen vrij te maken, wat u kunt bevestigen met sudo dmesg -T | grep -i 'killed process'.
WP-CLI voert de event-callbacks rechtstreeks uit in plaats van wp-cron.php aan te roepen, dus de lock van 60 seconden die WordPress gebruikt tegen dubbele spawns is hier niet van toepassing. flock -n in de invoer van stap 3 is wat overlap nu voorkomt. Een overgeslagen uitvoering sluit direct en geruisloos af, zoals ontworpen.
Kies het interval op basis van de kortste planning waar u daadwerkelijk afhankelijk van bent, en meet eerst een uitvoering:
time sudo -u www-data /usr/local/bin/wp --path=/srv/www/example.com cron event run --due-nowVijf minuten is een verstandige standaard: een bericht dat gepland staat voor 09:00 wordt uiterlijk om 09:05 gepubliceerd. Vijftien minuten is prima voor een site zonder tijdskritieke onderdelen. Eén minuut is voorbehouden aan webshops en wachtrij-gestuurde plugins die dit echt nodig hebben, en alleen als u weet dat een uitvoering binnen enkele seconden is voltooid.
Als u WP-CLI niet kunt installeren
Sommige hostingproviders blokkeren shell-tools. Een standaard HTTP-verzoek aan wp-cron.php voert dezelfde wachtrij uit, maar dan via de volledige webstack:
*/5 * * * * /usr/bin/curl -sS --max-time 120 "https://example.com/wp-cron.php?doing_wp_cron" > /dev/nullWat u hierbij inlevert:
- De uitvoering wordt beperkt door de time-outs van de webserver en PHP-FPM, waardoor een langdurige taak voortijdig kan worden afgebroken.
- Het certificaat moet geldig zijn, anders stopt
curlmetSSL certificate problem; zorg er dus voor dat vernieuwingen blijven werken via Certbot on nginx. - Pagina-caching mag
wp-cron.phpniet cachen, anders ontvangen cron-verzoeken een gecachte respons en wordt er niets uitgevoerd. - U krijgt geen output per gebeurtenis, dus het enige bewijs dat een taak is uitgevoerd, is het resultaat ervan.
-sS zorgt ervoor dat curl stil blijft bij succes, maar foutmeldingen wel toont; dit is de gewenste configuratie voor een cron-job.
Wat hoort er nog meer in de planning van de server
Zodra de system cron de WordPress-wachtrij beheert, kunt u de rest van de routinematige taken van de server op dezelfde plek onderbrengen, waar u ze kunt inzien. Beveiligingsupdates voor het besturingssysteem horen bij unattended upgrades in plaats van bij een cron-regel die u handmatig onderhoudt. Updates voor WordPress-plugins en -thema's zijn een andere afweging: wp plugin update --all in een crontab kan onbedoeld een live website om 03:00 uur onbereikbaar maken zonder dat iemand toezicht houdt. Voer dergelijke updates daarom bewust uit, of pas ze toe na een testfase en een back-up.
FAQ
Stopt het uitschakelen van WP-Cron het publiceren van geplande berichten?
Nee, zolang er iets anders is dat de wachtrij verwerkt. DISABLE_WP_CRON voorkomt alleen dat paginaladingen de wachtrij activeren. Gebeurtenissen worden nog steeds precies zoals voorheen gepland. Een bericht dat voor 09:00 is ingesteld, wordt gepubliceerd bij de eerste cron-run na 09:00; bij een interval van vijf minuten wordt het dus uiterlijk om 09:05 gepubliceerd. Als u de constante instelt maar de cron-entry niet toevoegt, blijft het bericht in de lijst staan met de status Missed schedule totdat iets de wachtrij uitvoert.
Welke gebruiker moet de WordPress cron-job uitvoeren?
De gebruiker die eigenaar is van de bestanden waar PHP naar schrijft; dit is www-data op een standaard Ubuntu-installatie. Controleer dit met stat -c '%U %G' /srv/www/example.com/wp-content/uploads en vergelijk dit met de regel user = in uw PHP-FPM pool-configuratie. Het uitvoeren van de job als root zorgt ervoor dat WP-CLI stopt met een YIKES-foutmelding, en het forceren hiervan met --allow-root resulteert in bestanden in wp-content die eigendom zijn van root, waar de webserver vervolgens niet naar kan schrijven.
Hoe vaak moet de systeem-cron de WordPress-cron uitvoeren?
Elke vijf minuten is voor de meeste sites voldoende. Stem het interval af op het kortste schema waar u echt op vertrouwt en houd het ruim boven de tijd die een enkele run in beslag neemt. U kunt dit meten door time voor het WP-CLI-commando te plaatsen. Intervallen van één minuut zorgen op een drukke site voor opgestapelde runs, tenzij flock deze bewaakt.
Waarom faalt wp cron test nadat ik WP-Cron heb uitgeschakeld?
Omdat dat commando test of het spawnen door bezoekers werkt, en het rapporteert een fout wanneer DISABLE_WP_CRON op true is ingesteld. Dat is het juiste resultaat op een server die op deze manier is geconfigureerd. Controleer in plaats daarvan het systeem-cronpad: lees /var/log/wp-cron/example.log, of plan een markeringsevenement met wp cron event schedule en bevestig dat het uit wp cron event list is verdwenen na de volgende run.
Heb ik WP-CLI nodig, of is curl naar wp-cron.php voldoende?
Curl werkt, en het is de juiste oplossing wanneer u WP-CLI niet kunt installeren. Het is trager omdat het WordPress via de webserver laadt en beperkt wordt door de request-timeout. WP-CLI voert de gebeurtenissen uit in een PHP-proces via de command line zonder web-timeout, en print per gebeurtenis één regel met de duur ervan, zodat het logbestand u precies vertelt wat er is uitgevoerd en hoe lang het duurde.