Kort svar: wp-cron kører kun, når nogen besøger sitet. Bekræft først, at hændelserne faktisk er forsinkede, og test derefter wp-cron.php direkte med en request. Svarer den 200, men opgaverne stadig hænger, er det typisk page cache, en firewall eller en ensom DISABLE_WP_CRON-linje, der blokerer. Den holdbare løsning er en rigtig server-cron hvert 5. minut – så kører opgaverne uanset trafik.
Fagligt gennemgået: 2. oktober 2026
Planlagte indlæg udgives ikke, backup-pluginet sprang natten over, og WooCommerce-mails kommer i klumper. Symptomerne ser forskellige ud, men årsagen er ofte den samme: wp-cron, WordPress’ interne opgavekø, bliver ikke udløst. wp-cron er nemlig ikke en rigtig cron – den kører kun, når en side bliver indlæst. Ingen besøg, ingen opgaver.
Guiden tager dig gennem diagnosen i den rækkefølge, der hurtigst afslører årsagen: Er køen reelt forsinket? Kan wp-cron.php overhovedet nås? Hvad blokerer? Og hvordan flytter du udløseren over på serveren, så problemet ikke kommer igen?
Før du ændrer noget: Tag en kopi af
wp-config.php, og notér hvilke cron-jobs der allerede findes i kontrolpanelet eller crontab. Slå aldrigDISABLE_WP_CRONtil, før server-cron er oprettet og har kørt mindst én gang – ellers stopper alle planlagte opgaver helt.
Sådan virker wp-cron – og derfor fejler den
Ved hver sideindlæsning tjekker WordPress, om der ligger forfaldne hændelser i cron-køen. Gør der det, sender WordPress en intern request (et såkaldt loopback-kald) til wp-cron.php, som afvikler opgaverne i baggrunden. Selve køen ligger som én samlet indstilling, cron, i tabellen wp_options, og en kortvarig lås forhindrer, at to besøg starter de samme opgaver samtidig. Låsen udløber som standard efter 60 sekunder (konstanten WP_CRON_LOCK_TIMEOUT).
Modellen er robust på et site med jævn trafik, men skrøbelig i disse situationer:
- Lav eller ujævn trafik: ingen besøg om natten betyder, at natlige opgaver først kører ved morgendagens første besøg.
- Aggressiv page cache: når næsten alle sider leveres fra cache, når PHP – og dermed cron-tjekket – sjældent at køre.
- Blokeret intern request: firewall, adgangskodebeskyttelse eller DNS-forhold kan forhindre serveren i at kalde sit eget
wp-cron.php. - En fastlåst eller tung opgave: et backup- eller importjob, der timer ud hver gang, kan få køen til at se død ud, selvom udløseren virker.
- En oppustet kø: plugins, der planlægger den samme hændelse igen og igen, kan fylde
cron-indstillingen med tusindvis af poster, så hver kørsel bliver langsom.
1. Bekræft at køen er forsinket
Gå til Værktøjer → Webstedstilstand. WordPress advarer selv, hvis en planlagt hændelse er sprunget over. Vil du se selve køen, viser pluginnet WP Crontrol hver hændelse med næste kørselstidspunkt, og med WP-CLI kan du liste køen og teste udløseren direkte:
wp cron event list --fields=hook,next_run_relative,recurrence
wp cron test

Notér, hvor længe hændelserne har ventet. Minutter er normalt. Timer betyder, at cron reelt ikke bliver udløst – og så skal du videre til trin 2. wp cron test fortæller desuden, om WordPress kan starte cron via loopback-kaldet; fejler testen, ved du allerede, at problemet ligger i forbindelsen og ikke i selve opgaverne.
Læg også mærke til, om det er alle hændelser, der er forsinkede, eller kun én bestemt. Er det kun én hook, der hænger, mens resten kører, er udløseren i orden – så er det opgaven bag den hook, der fejler. Find pluginnet, der ejer den, og tjek PHP-fejlloggen på kørselstidspunktet.
2. Test wp-cron.php direkte
Åbn https://ditdomæne.dk/wp-cron.php i browseren, eller kald den med curl. Siden skal svare med HTTP 200 og en tom side.
curl -sI https://eksempel.dk/wp-cron.php
Får du 403, rammer du en firewall- eller sikkerhedsregel. Får du 401, ligger der adgangskodebeskyttelse på sitet eller mappen. En timeout peger på, at en tung opgave i køen blokerer – typisk et backup- eller importjob, der aldrig bliver færdigt. Får du en 5xx-fejl, er der en PHP-fejl i en af opgaverne; serverens fejllog på samme tidspunkt viser, hvilken.
Tjek samtidig wp-config.php for linjen define( 'DISABLE_WP_CRON', true );. Den er korrekt, hvis der også er sat en server-cron op. Står den alene – for eksempel som rest fra en tidligere hostingudbyder – er den hele forklaringen: cron er slået fra, uden at noget andet tager over.
wp config get DISABLE_WP_CRON
grep -n "DISABLE_WP_CRON\|ALTERNATE_WP_CRON" wp-config.php
3. Find blokeringen
| Det du ser | Sandsynlig årsag | Rettelse |
|---|---|---|
| 200, men opgaver hænger stadig | Page cache leverer alt; PHP kører sjældent | Skift til server-cron (trin 4) |
| 403 ved kald af wp-cron.php | Firewall eller sikkerhedsplugin blokerer filen | Undtag wp-cron.php for serverens egen IP |
| 401 ved kald | Adgangskodebeskyttelse på site eller mappe | Undtag filen, eller kør cron via PHP i stedet for HTTP |
| Timeout ved kald | En fastlåst, tung opgave i køen | Find og fjern hændelsen med WP Crontrol |
wp cron test fejler | Loopback-kaldet når ikke frem | Se guiden om loopback- og cURL-fejl |
| Samme hook står hundredvis af gange | Plugin planlægger dubletter | Opdatér eller fjern pluginnet, og ryd hooken |
| Én hook fejler, resten kører | PHP-fejl eller tidsgrænse i netop den opgave | Læs fejlloggen; se Maximum execution time exceeded |
Har et plugin fyldt køen med dubletter, kan du rydde alle hændelser for en bestemt hook med WP-CLI. Kør først listen, så du er sikker på navnet, og ret derefter årsagen – ellers planlægger pluginnet bare dubletterne igen:
wp cron event list --fields=hook --format=count
wp cron event delete plugin_navn_hook
ALTERNATE_WP_CRON som nødløsning
Kan serveren ikke kalde sig selv, og kan du ikke oprette en server-cron, findes konstanten ALTERNATE_WP_CRON. Den får WordPress til at køre cron via en omdirigering af den besøgendes request i stedet for loopback-kaldet. Det virker, men det tilføjer ?doing_wp_cron til URL’er og spiller dårligt sammen med cache. Brug det kun midlertidigt, indtil den rigtige løsning er på plads.
4. Skift til rigtig server-cron
Den holdbare løsning fjerner afhængigheden af trafik helt. Den består af to dele, og rækkefølgen er vigtig:
- Opret et cron-job i hostingens kontrolpanel eller crontab, der kører hvert 5. minut – enten ved at kalde
https://ditdomæne.dk/wp-cron.php?doing_wp_croneller ved at kørephp wp-cron.phpdirekte fra WordPress-mappen. - Slå derefter den trafikafhængige cron fra i
wp-config.phpmeddefine( 'DISABLE_WP_CRON', true );– lige over linjen „That’s all, stop editing“.
Der er tre gængse måder at skrive selve cron-jobbet på. Stierne er eksempler; brug den sti, dit site faktisk ligger i:
# A: PHP direkte – uden om webserver, cache og firewall
*/5 * * * * cd /sti/til/wordpress && php wp-cron.php > /dev/null 2>&1
# B: WP-CLI – kører kun de hændelser, der er forfaldne
*/5 * * * * cd /sti/til/wordpress && wp cron event run --due-now > /dev/null 2>&1
# C: HTTP-kald – når du ikke kan køre kommandoer på serveren
*/5 * * * * curl -s "https://eksempel.dk/wp-cron.php?doing_wp_cron" > /dev/null 2>&1
Variant A og B er at foretrække, fordi de ikke går gennem webserveren og derfor ikke kan blokeres af cache, firewall eller adgangskodebeskyttelse. Sørg for, at php i cron-jobbet er den samme PHP-version som sitet bruger – på servere med flere PHP-versioner er standardkommandoen ikke altid den rigtige. Variant C går den samme vej som en besøgende og rammer derfor de samme blokeringer som i trin 3.
/* Sæt kun denne linje, når server-cron kører */
define( 'DISABLE_WP_CRON', true );
Opgaverne er præcis de samme som før; de bliver bare udløst af serveren i stedet for af tilfældige besøg. Hos de fleste udbydere opretter du cron-jobs i kontrolpanelet. Er du hos Hostious og i tvivl om stien eller intervallet, hjælper den danske support gerne med opsætningen.
Multisite: én kø pr. site
På en WordPress-multisite har hvert site sin egen cron-kø. Et enkelt kald til hovedsitets wp-cron.php afvikler ikke undersitenes opgaver. Med WP-CLI kan ét cron-job løbe alle sites igennem:
*/5 * * * * cd /sti/til/wordpress && wp site list --field=url | xargs -I % wp cron event run --due-now --url=% > /dev/null 2>&1
„Missed schedule“ på planlagte indlæg
Fejlen „Missed schedule“ („planlagt tidspunkt overskredet“) på et indlæg er ikke en selvstændig fejl – det er wp-cron-problemet set fra redaktionens side. Indlægget skulle udgives på et tidspunkt, hvor ingen cron kørte. Når server-cron er sat op, forsvinder problemet fremadrettet. Indlæg, der allerede er ramt, udgiver du manuelt ved at åbne dem og klikke Udgiv igen.
Tjek også sitets tidszone under Indstillinger → Generelt. Står den på UTC i stedet for København, rammer planlagte indlæg konsekvent en eller to timer forkert afhængigt af sommer- og vintertid – det ligner en cron-fejl, men er en indstilling. Vælg byen „København“ frem for en fast UTC-forskel, så sommertid håndteres automatisk.
WooCommerce, Action Scheduler og cron
WooCommerce og mange andre plugins bruger biblioteket Action Scheduler til deres baggrundsopgaver: ordremails, webhooks, abonnementsfornyelser og databaseopdateringer. Action Scheduler har sin egen kø, men den bliver primært sat i gang af wp-cron. Står cron stille, hober planlagte handlinger sig derfor op under WooCommerce → Status → Planlagte handlinger.
Server-cron er derfor også den første rettelse, når en webshop har forfaldne handlinger eller en databaseopdatering, der aldrig bliver færdig. Har shoppen mange ordrer, kan et interval på hvert minut være en fordel. Se guiderne om forfaldne planlagte handlinger og en hængende databaseopdatering.
Verifikation
Rettelsen er dokumenteret, når:
- Webstedstilstand ikke længere viser cron-advarsler;
- cron-køen er tom for forfaldne hændelser flere timer i træk – også uden besøg;
- et testindlæg planlagt fem minutter ude i fremtiden udgives til tiden;
- kontrolpanelets cron-log viser en kørsel hvert 5. minut uden fejl;
- eventuelle WooCommerce-handlinger ikke længere står som forfaldne.
Fortryder du, fjerner du blot DISABLE_WP_CRON-linjen og sletter cron-jobbet – så er den trafikudløste model tilbage. Hænger opgaverne stadig efter skiftet, er det køens indhold og ikke udløseren, der er problemet; find den fastlåste hændelse med WP Crontrol, eller kontakt Hostious, hvis du vil have hjælp til at læse cron- og fejlloggen.
Hvornår skal du have hjælp?
Du kan selv klare det meste i denne guide med adgang til wp-admin og kontrolpanelet. Få hjælp, hvis du ikke kan oprette cron-jobs, hvis serverens firewall blokerer interne kald, eller hvis en bestemt opgave fejler med PHP-fejl, du ikke kan placere. Giv i så fald besked om, hvilken hook der hænger, hvornår den sidst kørte, og hvad wp cron test eller kaldet til wp-cron.php svarede.
Læs også
- Hub: WordPress fejl og fejlfinding
- Forfaldne planlagte handlinger i WooCommerce
- cURL error 28 og loopback-fejl i Site Health
- Planlagte opgaver, der bare kører: cron uden wp-cron-fælder
- WP-CLI for begyndere – 10 opgaver, du aldrig mere gør i hånden
- WordPress hosting hos Hostious – LiteSpeed, daglig backup og dansk support 24/7
Ofte stillede spørgsmål om wp-cron
Hvorfor udgives mine planlagte indlæg ikke?
Fordi wp-cron kun kører ved besøg. Var der ingen trafik på udgivelsestidspunktet, får indlægget status „Missed schedule“. En server-cron hvert 5. minut løser det permanent.
Er det sikkert at slå wp-cron fra?
Ja – når DISABLE_WP_CRON kombineres med et rigtigt cron-job, der kalder wp-cron.php. Opgaverne er de samme; kun udløseren ændres. Slå den aldrig fra uden at sætte server-cron op først.
Hvor ofte skal server-cron køre?
Hvert 5. minut er standard og passer til de fleste sites. Webshops med mange ordremails og planlagte handlinger kan gå ned til hvert minut; sjældnere end hvert 15. minut giver mærkbare forsinkelser.
Hvad er forskellen på wp-cron og server-cron?
wp-cron er WordPress’ egen opgavekø, som udløses af besøg. Server-cron er serverens tidsstyring, der kører på faste tidspunkter. Den bedste opsætning bruger server-cron som udløser af wp-cron, så opgaverne kører til tiden uanset trafik.
Hvorfor kører en opgave nogle gange to gange?
Hvis en opgave tager længere end cron-låsens 60 sekunder, kan næste udløsning starte den igen, før den første er færdig. Løsningen er at gøre opgaven hurtigere eller dele den op – ikke at køre cron oftere.
Udgivet 30. august 2026Opdateret 3. oktober 2026Fagligt gennemgået 2. oktober 2026
