WP-Cron Non È un Cron. Ed È Probabilmente Rotto sul Tuo Sito.
WordPress ha un sistema di schedulazione chiamato WP-Cron. Il nome è fuorviante. Non è un cron job. Non gira in background a intervalli regolari. Si attiva solo quando qualcuno visita il sito.
Se il tuo sito ha 100 visite al giorno, WP-Cron funziona più o meno. Se ne ha 5, i task schedulati accumulano ritardo. Se ne ha 0 (sito in staging, sito nuovo), WP-Cron non gira mai.
Per un sito personale, questo non è un problema. Per un’agenzia che gestisce backup automatici, report AI, scansioni di sicurezza e monitoraggio uptime su decine di siti, è un disastro silenzioso.
Come Funziona WP-Cron (e Perché Fallisce)
Il meccanismo:
- Un utente visita il sito
- WordPress controlla: “ci sono task schedulati scaduti?”
- Se sì, apre una richiesta HTTP a
wp-cron.phpin background wp-cron.phpesegue i task scaduti
I problemi:
| Problema | Conseguenza | Frequenza |
|---|---|---|
| Nessuna visita = nessun trigger | Task non eseguiti per ore/giorni | Molto comune su siti a basso traffico |
| Troppo traffico = troppi trigger | WP-Cron eseguito a ogni pageview, spreco risorse | Comune su siti ad alto traffico |
| Task lungo blocca la pagina | Timeout, pagina bianca per l’utente | Quando il task dura più di 30 secondi |
| Hosting blocca wp-cron.php | Nessun task eseguito, mai | Alcuni hosting condivisi lo disabilitano |
| Task duplicati | Lo stesso task gira 3-4 volte | Bug noti con plugin di cache |
La Soluzione: Cron Reale del Sistema Operativo
Il fix è semplice: disabilita WP-Cron e usa il cron del sistema operativo (crontab) per triggerare wp-cron.php a intervalli fissi.
Step 1: disabilita WP-Cron
Aggiungi in wp-config.php:
define('DISABLE_WP_CRON', true);
Questo impedisce a WordPress di triggerare WP-Cron a ogni visita. I task schedulati restano nel database, ma non vengono più eseguiti dal traffico.
Step 2: configura il cron di sistema
# Apri il crontab dell'utente web (www-data su Debian/Ubuntu)
sudo crontab -u www-data -e
# Aggiungi questa riga: esegui wp-cron ogni 5 minuti
*/5 * * * * cd /var/www/html && php wp-cron.php > /dev/null 2>&1
# Alternativa con wget (se non hai accesso PHP CLI)
*/5 * * * * wget -q -O - https://tuosito.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1
# Alternativa con WP-CLI (la migliore)
*/5 * * * * cd /var/www/html && wp cron event run --due-now > /dev/null 2>&1
WP-CLI è l’opzione migliore: non passa per HTTP (niente timeout web server), mostra gli errori in modo chiaro, e puoi testarlo manualmente.
Step 3: verifica che funzioni
# Lista dei task schedulati con WP-CLI
wp cron event list
# Output esempio:
# +---------------------------+---------------------+-----------+
# | hook | next_run | recurrence|
# +---------------------------+---------------------+-----------+
# | wp_update_plugins | 2026-03-25 09:00:00 | twicedaily|
# | ai_daily_health_check | 2026-03-25 00:00:00 | daily |
# | generate_monthly_reports | 2026-04-01 08:00:00 | monthly |
# +---------------------------+---------------------+-----------+
# Esegui manualmente tutti i task scaduti
wp cron event run --due-now
# Esegui un task specifico
wp cron event run ai_daily_health_check
Configurazioni per Scenari Specifici
Agenzia con 30 siti WordPress
Se gestisci 30 siti su uno o più server, crea uno script che li itera tutti:
#!/bin/bash
# /usr/local/bin/run-all-wp-crons.sh
SITES=(
"/var/www/site1"
"/var/www/site2"
"/var/www/site3"
# ... tutti i siti
)
for site_path in "${SITES[@]}"; do
if [ -f "$site_path/wp-cron.php" ]; then
cd "$site_path" && sudo -u www-data wp cron event run --due-now 2>&1 |
while read line; do
echo "[$(basename $site_path)] $line"
done
fi
done
# Nel crontab:
*/5 * * * * /usr/local/bin/run-all-wp-crons.sh >> /var/log/wp-crons.log 2>&1
WordPress su Docker
# Nel docker-compose.yml, aggiungi un servizio cron dedicato:
wp-cron:
image: wordpress:cli
volumes:
- wordpress_data:/var/www/html
entrypoint: >
sh -c 'while true; do
wp cron event run --due-now --path=/var/www/html;
sleep 300;
done'
depends_on:
- wordpress
Hosting condiviso (senza accesso SSH)
Se non hai accesso al crontab del server:
- cPanel: vai in “Cron Jobs” nel pannello e aggiungi
wget -q -O - https://tuosito.com/wp-cron.php?doing_wp_cron > /dev/null 2>&1 - Servizio esterno: usa cron-job.org (gratuito) o UptimeRobot per pingare
https://tuosito.com/wp-cron.phpogni 5 minuti - Plugin: WP Crontrol per gestire i task dalla dashboard (ma il problema di fondo resta)
Ottimizzare la Frequenza
Non tutti i task devono girare ogni 5 minuti:
| Task | Frequenza consigliata | Perché |
|---|---|---|
| Aggiornamenti plugin check | 2 volte/giorno | WordPress default, va bene così |
| Backup automatico | 1 volta/giorno | Meglio di notte, fuori orario di punta |
| Email di newsletter | Come schedulata | Non ritardare, gli utenti se ne accorgono |
| AI health check | 1 volta/giorno | Dati giornalieri sono sufficienti |
| Pulizia transient scaduti | 1 volta/giorno | Performance del database |
| WooCommerce scheduled sales | Ogni 5 minuti | Prezzi scontati devono attivarsi puntuali |
Regola pratica: il cron di sistema gira ogni 5 minuti. I task individuali hanno la loro frequenza (hourly, twicedaily, daily). WP-Cron internamente rispetta le frequenze. Il cron di sistema gli dice solo “svegliati e controlla”.
Debug: Quando il Cron Non Funziona
# 1. Verifica che DISABLE_WP_CRON sia attivo
wp config get DISABLE_WP_CRON
# Deve mostrare: true
# 2. Lista task in ritardo (dovrebbero essere 0 se il cron funziona)
wp cron event list --fields=hook,next_run | grep -v "^+"
# 3. Test manuale
wp cron event run --due-now --verbose
# 4. Controlla i log del cron di sistema
grep "wp-cron\|wp cron" /var/log/syslog | tail -20
# 5. Se usi wget, verifica che il sito risponda
curl -I https://tuosito.com/wp-cron.php?doing_wp_cron
FAQ
Disabilitare WP-Cron rompe qualche plugin?
No, se configuri il cron di sistema come sostituto. I plugin schedulano i task normalmente con wp_schedule_event(). La differenza è solo nel trigger: invece del traffico, il trigger è il cron di sistema. Tutti i plugin compatibili con WP-Cron funzionano con il cron di sistema.
Ogni 5 minuti è troppo? O troppo poco?
Per la maggior parte dei siti, 5 minuti è il punto ottimale. Il carico aggiuntivo è trascurabile (una esecuzione PHP di 1-2 secondi). Se hai task che richiedono precisione al minuto (aste, countdown), puoi scendere a 1 minuto. Per siti statici con pochi task, 15 minuti è sufficiente.
WP-CLI è meglio di wget per il cron?
Sì, per tre motivi: 1) non passa per il web server (niente timeout HTTP), 2) mostra errori in modo leggibile nei log, 3) non richiede che il sito sia accessibile via HTTP (funziona anche in manutenzione). L’unico requisito è che WP-CLI sia installato sul server.