SSD Nodes Learn Hosting plans →
Gidsen Matt ConnorDoor Matt Connor · Bijgewerkt 2026-08-28

WordPress wp-cron uitschakelen en system cron instellen

WP-Cron draait alleen bij paginabezoek, wat zorgt voor vertragingen of gemiste taken. Gebruik WP-CLI om dit naar een betrouwbare system cron te verplaatsen en taken te verifiëren.

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 helemaal geen.

Twee regels voeren het eigenlijke werk uit: een constante in wp-config.php en een crontab-item. Al het overige in deze handleiding betreft zaken die deze twee regels niet vermelden. Onder welke gebruiker de taak moet draaien, hoe u bewijst dat de geplande gebeurtenissen daadwerkelijk zijn uitgevoerd, 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 gebruikersnaam.

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 roept bij een geplande taak spawn_cron() aan, wat 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 met PHP-FPM en pm.max_children = 5 houdt één trage geplande taak een vijfde van uw PHP-capaciteit bezet zolang deze duurt. Dit gebeurt meestal tijdens uw drukste minuut, omdat er dan de meeste pagina's worden geladen.

WordPress beperkt duplicaten. Het zet een lock met een levensduur van WP_CRON_LOCK_TIMEOUT, standaard 60 seconden, zodat gelijktijdige bezoekers niet elk een taak starten. De lock beperkt duplicatie. Het verplaatst het werk echter niet buiten het verzoekpad.

Tel hoe vaak dit op uw eigen server wordt geactiveerd voordat u besluit of het relevant is. Elke loopback verschijnt in het access log van de webserver:

sudo grep -c 'wp-cron.php' /var/log/nginx/access.log

Apache schrijft in plaats daarvan naar /var/log/apache2/access.log. Een aantal van duizenden per dag is een reële kostenpost. Dit is het type getal dat u op uw eigen systeem 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 de situatie. Als een paginacache de meeste verzoeken als statische HTML serveert, wordt PHP voor die verzoeken nooit uitgevoerd en vindt de cron-controle dus nooit plaats. Een zwaar gecachte, drukke site gaat zich gedragen als de rustige site hieronder.

Waarom cron-taken op een rustige website niet worden uitgevoerd

Geen bezoekers betekent geen cron. Een website die slechts enkele bezoeken per dag ontvangt, voert de geplande taken slechts een paar keer per dag uit, op de willekeurige momenten dat die bezoeken plaatsvinden.

De symptomen zijn telkens hetzelfde. Een bericht dat voor 09:00 is gepland, blijft in de berichtenlijst gemarkeerd als Missed schedule totdat iemand een pagina laadt. Back-upplugins slaan de nacht over. Updates worden niet tijdig gecontroleerd, waardoor het dashboard geen updates toont terwijl er al een beveiligingsupdate beschikbaar is. Bestelmails, verlengingsberichten en waarschuwingen voor verloopdata worden te laat verzonden.

Dit levert geen foutmelding op in de logs. Voor WordPress was de taak nooit te laat, omdat deze simpelweg nooit is gestart.

Stap 1: schakel de visitor trigger uit 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 die opmerking wp-settings.php vereist, en wp-settings.php het punt is waar WordPress de cron-controle aan init koppelt. Een constante die na die require wordt gedefinieerd, wordt te laat ingesteld om nog effect te hebben; het bestand ziet er correct uit, maar de trigger blijft actief.

Controleer of de regel op de juiste plek staat:

grep -n "DISABLE_WP_CRON\|stop editing" /srv/www/example.com/wp-config.php

De constante voorkomt niet dat taken worden gepland. 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 opvragen, wat meestal ongevaarlijk is omdat het bestand alleen taken uitvoert die 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 ten opzichte van de PHP-module voor de webserver.

php -v
sudo apt install -y php-cli

Installeer WP-CLI via 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 --info

php 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 version

Als 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 in de eerste foutmodus hieronder uitgelegd.

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 correct wordt uitgevoerd.

Controleer nu of WordPress zelf 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 deze onder de require-regel 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.conf

Op 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 heeft gegeven, wat meestal het eindresultaat is van een per-site configuratie op een LAMP-stack op Ubuntu 24.04, gebruik dan die gebruiker voor alle onderstaande stappen.

Maak een logmap aan waar die gebruiker naar kan schrijven:

sudo install -d -o www-data -g www-data -m 750 /var/log/wp-cron

Bewerk de crontab van die gebruiker:

sudo crontab -u www-data -e

Voeg éé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>&1

Stap voor stap. */5 voert de taak 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 vereist is voor cron. --path zorgt ervoor dat het commando vanuit elke werkmap kan worden uitgevoerd. --due-now voert alleen de events uit waarvan de tijd is aangebroken, in plaats van elk event in de wachtrij. De redirect stuurt normale output en foutmeldingen naar één bestand dat u kunt inzien.

Die redirect is in de praktijk niet optioneel. Cron mailt de output 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 output weg. Een bestand bewaart het bewijs.

Controleer of het bestand is opgeslagen:

sudo crontab -u www-data -l

Gebruik voor meerdere sites per site één regel met verspringende minuten, 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>&1

Het logbestand blijft groeien 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 de configuratie 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 wp

Een 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.log

WP-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 uitvoeringen is er niets gepland en wordt er weinig geschreven; lees het bestand daarom na een uitvoering waarvan u weet dat er werk klaarstond.

Controleer ten derde het volledige proces. Plan een markering-event 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_check

Wacht één interval en voer het list-commando opnieuw uit. De hook is verdwenen, omdat een eenmalig event uit de wachtrij wordt verwijderd zodra het is 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 dan of het probleem bij cron of bij WP-CLI ligt.

Gebruik hiervoor niet wp cron test. Dat commando controleert of het door bezoekers getriggerde opstarten 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 systemd timer-alternatief

Als de overige geplande taken op de server al worden uitgevoerd via systemd services en timers, breng WordPress dan ook daar onder. Elke uitvoering is dan zichtbaar in systemctl list-timers en de output wordt naar de journal gestuurd in plaats van naar een bestand dat u moet roteren.

Schrijf /etc/systemd/system/wp-cron-example.service:

[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-now

Vervolgens /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.target
sudo 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 20

Systemd voert niet twee kopieën van dezelfde service tegelijkertijd uit, dus deze versie heeft geen flock nodig. Persistent=true zorgt ervoor dat een taak die gemist is terwijl de machine uitstond alsnog wordt ingehaald; dit is iets wat een crontab-item niet kan.

Kies voor ofwel de crontab of de timer. Wanneer u beide tegelijkertijd voor dezelfde site gebruikt, 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 de melding nooit. De gevaarlijke oplossing is het toevoegen van --allow-root, omdat elk bestand dat een plugin tijdens die uitvoering 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 vervolgens de taak:

sudo chown -R www-data:www-data /srv/www/example.com/wp-content

De crontab van root en de crontab van www-data zijn afzonderlijke bestanden, dus het verwijderen van de regel uit de een heeft geen invloed op de ander. Controleer beide:

sudo crontab -u root -l
sudo crontab -u www-data -l

Waarom cron meldingen geeft over wp: not found

Dit is de tweede veelvoorkomende fout. Cron geeft aan taken van gebruikers een zeer beperkt PATH, /usr/bin:/bin. WP-CLI wordt geïnstalleerd in /usr/local/bin, wat niet op die lijst staat. De taak start, faalt binnen een fractie van een seconde en het logbestand bevat één regel:

/bin/sh: 1: wp: not found

Bekijk de omgeving van cron zelf in plaats van te gokken. Voeg een tijdelijke regel toe:

*/5 * * * * env > /tmp/cron-env.txt 2>&1

Lees /tmp/cron-env.txt na één interval en verwijder de regel daarna weer. De PATH=-waarde 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 aan het begin van de crontab, boven elke taakregel:

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

Dezelfde valkuil bevindt zich een 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 via controlepanelen, krijgt u:

/usr/bin/env: 'php': No such file or directory

Roep 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, die elk hun eigen geheugen en databaseverbinding vasthouden.

Controleer direct op een opstopping:

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 direct uit in plaats van wp-cron.php aan te roepen, waardoor de lock van 60 seconden die WordPress gebruikt tegen dubbele spawns hier niet van toepassing is. flock -n in de invoer van stap 3 is wat overlap nu voorkomt. Een overgeslagen uitvoering stopt direct en geruisloos, zoals ontworpen. Overlap is een probleem dat u in de crontab moet oplossen in plaats van iets dat de host-kernel voor u oplost: zelfs de cache-aware taakplaatsing toegevoegd in Linux kernel 7.2 bepaalt alleen op welke core een proces terechtkomt, nooit hoeveel u er daarvan heeft gestart.

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-now

Vijf minuten is een verstandige standaard: een bericht dat gepland staat voor 09:00 wordt gepubliceerd om 09:05. Vijftien minuten is prima voor een site zonder tijdskritieke taken. Eén minuut is voorbehouden aan webshops en wachtrij-gestuurde plugins die dit echt nodig hebben, en alleen als u weet dat een uitvoering in enkele seconden klaar is.

Als u WP-CLI niet kunt installeren

Sommige hostingproviders blokkeren shell-tools. Een simpel 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/null

Wat u hierbij inlevert:

  • De uitvoering wordt beperkt door de request-timeouts van de webserver en PHP-FPM, waardoor een langdurige taak halverwege kan worden afgebroken.
  • Het certificaat moet geldig zijn, anders stopt curl met SSL certificate problem; zorg er dus voor dat vernieuwingen blijven werken via Certbot op nginx.
  • Pagina-caching mag wp-cron.php niet cachen, anders krijgen 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 wel foutmeldingen 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 in één oogopslag ziet. Beveiligingsupdates voor het besturingssysteem horen thuis bij unattended upgrades in plaats van in 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 's nachts onbruikbaar maken zonder dat iemand het merkt. 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 stopt alleen het triggeren van de wachtrij bij het laden van pagina's. Gebeurtenissen worden nog steeds exact zoals voorheen gepland. Een bericht dat is ingesteld voor 09:00 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 nooit de cron-entry toevoegt, blijft het bericht in de lijst staan met de status Missed schedule totdat de wachtrij wordt uitgevoerd.

Welke gebruiker moet de WordPress cron-job uitvoeren?

De gebruiker die eigenaar is van de bestanden waarnaar PHP 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 het met de user =-regel 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, waardoor de webserver er later niet meer 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 het door bezoekers getriggerde opstarten test, 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-cron-pad: lees /var/log/wp-cron/example.log, of plan een markeringsevenement met wp cron event schedule en bevestig dat het na de volgende run uit wp cron event list is verdwenen.

Heb ik WP-CLI nodig, of is curl naar wp-cron.php voldoende?

Curl werkt, en het is het juiste antwoord 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.