WP Cron Non Si Esegue Quando Il Tempo Scade

27 mar 2013, 17:12:16
Visualizzazioni: 22K
Voti: 19

L'obiettivo

Voglio utilizzare wp_schedule_single_event() per eseguire un evento singolo che mi invii un'email 8 minuti dopo che l'utente invia un modulo.

Il problema

Il seguente codice è nel mio functions.php:

function nkapi_send_to_system( $args ) {
  wp_mail( 'xxx', 'xxx', $args );
}

add_action( 'nkapi_send', 'nkapi_send_to_system' );

function schedule_event( $id ) {
  wp_schedule_single_event( current_time( 'timestamp' ) + 480, 'nkapi_send', array( $id ) );
}

E il seguente codice viene utilizzato per chiamare schedule-event:

schedule_event( $_SESSION['insert_id'] ); // la variabile $_SESSION contiene un INT

Dopo aver atteso più di 8 minuti non c'era nessuna email nella mia casella di posta.

Cosa ho provato

Con il plugin Core Control è possibile vedere quali cron job sono programmati.

Schermata di Core Control che mostra i cron job programmati

Dopo un paio di modifiche sono riuscito a configurarli abbastanza correttamente e, ancora meglio, quando clicco su "Run Now", ricevo effettivamente un'email nella mia casella di posta.

Ma perché i cron non si eseguono quando visito il mio sito dopo 8 minuti? Cosa potrebbe esserci di sbagliato in questo codice? Devo dire che è la mia prima volta con WP Cron.

Ho provato altro

Dopo il commento di vancoder ho deciso di testare se il codice funziona inserendo direttamente il seguente codice nel functions.php:

function schedule_event( $id ) {
  wp_schedule_single_event( time(), 'nkapi_send', array( $id ) );
}

if ( isset( $_SESSION['insert_id'] ) ) {
  if ( ! array_key_exists( 'insert_scheduled', $_SESSION ) || $_SESSION['insert_scheduled'] != $_SESSION['insert_id'] ) {
    schedule_event( $_SESSION['insert_id'] );
    $_SESSION['insert_scheduled'] = $_SESSION['insert_id'];
  }
}

Lo svantaggio di questo codice è che l'utente deve andare su un'altra pagina prima che questo codice venga eseguito. Ma d'altra parte, questo non funziona neanche, quindi non sarebbe il mio primo problema...

5
Commenti

Dove e come viene eseguito schedule_event( $_SESSION['insert_id'] );?

vancoder vancoder
27 mar 2013 18:23:31

Uno shortcode include un file separato (con un form al suo interno) in una pagina, quando quel form viene inviato la pagina si ricarica, lo stesso file poi esegue la funzione schedule_event( ), diciamo all'inizio del file incluso caricato dallo shortcode.

Mike Madern Mike Madern
28 mar 2013 09:48:50

Funziona qualunque cron? wp_version_check etc?

vancoder vancoder
28 mar 2013 19:28:37

Non sono riuscito a far funzionare alcun cron. Quale potrebbe essere il problema?

Mike Madern Mike Madern
29 mar 2013 10:09:15

Per confermare - falliscono anche i cron job di base?

vancoder vancoder
4 apr 2013 19:44:42
Tutte le risposte alla domanda 6
8
18

Innanzitutto, definisci i tuoi programmi personalizzati per i cron job.

add_filter('cron_schedules', array($this, 'cron_schedules'));

public function cron_schedules($schedules){
    $prefix = 'cron_';// Evita conflitti con altri cron. Esempio di riferimento: cron_30_mins
    $schedule_options = array(
        '30_mins' => array(
            'display' => '30 Minuti',
            'interval' => '1800'
        ),
        '1_hours' => array(
            'display' => 'Ora',
            'interval' => '3600'
        ),
        '2_hours' => array(
            'display' => '2 Ore',
            'interval' => '7200'
        )
    );
    /* Aggiungi ogni programma personalizzato nel sistema dei cron job. */
    foreach($schedule_options as $schedule_key => $schedule){
        $schedules[$prefix.$schedule_key] = array(
            'interval' => $schedule['interval'],
            'display' => __('Ogni '.$schedule['display'])
        );
     }
     return $schedules;
}

Devi decidere dove e quando programmare effettivamente l'evento.

Ecco un esempio di snippet di codice, che effettua una chiamata a un metodo personalizzato di classe:

$schedule = $this->schedule_task(array(
    'timestamp' => current_time('timestamp'), // Determina quando programmare il task.
    'recurrence' => 'cron_30_mins',// Scegli uno dei programmi impostati in precedenza.
    'hook' => 'custom_imap_import'// Imposta il nome del tuo cron task.
));

Ecco il codice che effettivamente programma l'evento:

private function schedule_task($task){
    /* Deve avere le informazioni del task. */
    if(!$task){
        return false;
    }
    /* Imposta l'elenco delle chiavi necessarie per il task. */
    $required_keys = array(
        'timestamp',
        'recurrence',
        'hook'
    );
    /* Verifica che esistano le informazioni necessarie per il task. */
    $missing_keys = array();
    foreach($required_keys as $key){
        if(!array_key_exists($key, $task)){
            $missing_keys[] = $key;
        }
    }
    /* Controlla le chiavi mancanti. */
    if(!empty($missing_keys)){
        return false;
    }
    /* Il task non deve essere già programmato. */
    if(wp_next_scheduled($task['hook'])){
        wp_clear_scheduled_hook($task['hook']);
    }
    /* Programma l'esecuzione del task. */
    wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
    return true;
}

Ora, tutto ciò che devi fare è effettuare una chiamata al nome del tuo cron task personalizzato. In questo esempio il nome del cron task è custom_imap_import.

add_action('custom_imap_import', array($this, 'do_imap_import'));

public function do_imap_import(){
    // .... Esegui operazioni quando il cron viene attivato ....
}

Quindi, in questo esempio, $this->do_imap_import(); viene chiamato ogni 30 minuti (supponendo che ci sia abbastanza traffico sul tuo sito web).


Note

Richiede una visita alla pagina affinché il tuo cron venga eseguito agli orari corretti.

Esempio: Se hai programmato un task a intervalli di 30 minuti, ma nessuno visita il tuo sito per 4 ore, il tuo cron job non verrà eseguito fino a quando un visitatore non arriverà sul tuo sito dopo 4 ore. Se hai davvero bisogno che il tuo task venga eseguito ogni 30 minuti, è consigliabile configurare un vero cron job tramite il tuo provider di hosting per visitare il tuo sito agli intervalli desiderati.

I cron job di WordPress non rallentano il tuo sito web!

Forse ti stai chiedendo: e se lo script del cron impiega molto tempo per essere eseguito, i visitatori dovranno aspettare fino al completamento dello script? No! Come è possibile? Se guardi il file wp-cron.php troverai una riga

ignore_user_abort(true);

È una configurazione di php.ini che imposta che se interrompi il caricamento del sito/script, lo script non si fermerà.

Se guardi il file wp-includes/cron.php troverai una riga come questa:

wp_remote_post( $cron_url, 
array('timeout' => 0.01,
 'blocking' => false, 
 'sslverify' => apply_filters('https_local_ssl_verify', true)) );

Ciò significa che WordPress attenderà solo 0.01 secondi per attivare l'esecuzione, poi interromperà la connessione ma, poiché hai impostato ignore_user_abort a true, lo script continuerà a essere eseguito. Questa funzionalità è un enorme vantaggio per eseguire script complessi nei cron job di WordPress.

Funzioni disponibili per aiutarti:

4 apr 2013 17:22:45
Commenti

Questa è una risposta straordinariamente completa che, per quanto posso vedere, non affronta la vera domanda - ovvero perché tutti i task programmati (compresi quelli core) falliscono.

vancoder vancoder
4 apr 2013 19:40:42

Questa risposta ha lo scopo di guidare l'utente nella giusta direzione per comprendere e programmare correttamente i task cron di WordPress.

Michael Ecklund Michael Ecklund
4 apr 2013 20:07:54

Questo mi ha sicuramente aiutato molto a capire le pianificazioni cron con WordPress

Mike Madern Mike Madern
9 apr 2013 16:08:17

Michael, dovresti rispondere più spesso. Ottimo +1

kaiser kaiser
3 ott 2013 05:36:35

A che punto dovresti fare "add_action('custom_imap_import', array($this, 'do_imap_import'))", assumendo una classe di plugin? Nel costruttore?

codecowboy codecowboy
11 ott 2013 20:25:13

@codecowboy Sì, o da qualche parte possa essere caricato quando il cron è pronto per essere eseguito.

Michael Ecklund Michael Ecklund
21 ott 2013 23:12:25

Il core fornisce già un intervallo hourly, quindi non è necessario utilizzare 1_hours.

Ian Dunn Ian Dunn
25 nov 2014 03:06:29

Credo che WP_Cron utilizzi GMT internamente, come il resto di WP, quindi sarebbe meglio programmare il primo evento usando time() invece di current_time().

Ian Dunn Ian Dunn
25 nov 2014 03:09:08
Mostra i restanti 3 commenti
2

Per prima cosa, puoi confermare di non avere alcun plugin di caching attivato? I plugin di caching possono interferire con i cron job perché i tuoi visitatori non ricevono una pagina live ma una versione memorizzata nella cache della tua pagina.

Se hai un plugin di caching attivo, puoi scegliere una delle tue pagine, aggiungere un'esclusione nelle impostazioni del tuo plugin di caching per quella pagina in modo che non venga mai memorizzata nella cache.

Dopodiché dovrai creare manualmente un cron job (usando cpanel se sei su un ambiente di hosting condiviso o dal terminale se si tratta di un server VPS/dedicato) che visiterà quella pagina ogni pochi minuti.

Spero che questo ti aiuti!

5 apr 2013 17:59:13
Commenti

Ho un plugin di caching attivo! Per la precisione W3 Total Cache

Mike Madern Mike Madern
9 apr 2013 16:04:55

Ci sono opzioni per disabilitare tutta la cache, ma non vedo un'opzione per abilitare/disabilitare la cache solo per i plugin

user1019042 user1019042
2 nov 2020 21:53:06
1

WordPress Cron ti consente di pianificare attività, ma queste verranno eseguite solo se viene effettuata una richiesta al sito. Per ogni richiesta che WordPress riceve, controllerà se ci sono lavori cron da elaborare e, in caso affermativo, invierà una richiesta asincrona a /wp-cron.php?doing_wp_cron per elaborare il lavoro. Se l'orario programmato di inizio di un lavoro passa senza una richiesta, il processo cron non verrà avviato.

Poiché sei in grado di visualizzare ed eseguire i tuoi lavori pianificati, è possibile che non ci siano richieste che attivino l'avvio del lavoro cron, specialmente se stai utilizzando un plugin di caching. L'opzione migliore per delegare questo a una pianificazione più regolare è disabilitare il controllo predefinito in WordPress e utilizzare crontab.

Innanzitutto, per disabilitare il controllo predefinito (che può aiutare un po' con le prestazioni lato client), aggiungi quanto segue a wp-config.php:

// Disabilita il controllo predefinito per i lavori cron di WordPress durante il caricamento delle pagine
define( 'DISABLE_WP_CRON', true );

Successivamente, crei un'attività per recuperare la pagina wp-cron.php una volta al minuto per elaborare eventuali lavori sul backend, dalla riga di comando inserisci crontab -e e poi aggiungi una riga simile alla seguente:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
6 apr 2013 03:43:17
Commenti

Se non assegni un valore a doing_wp_cron, è molto probabile che i job vengano eseguiti due volte occasionalmente. Usa doing_wp_cron=$(date +\%s.\%N) per evitare che ciò accada.

Alexander Garden Alexander Garden
10 nov 2013 13:04:14
0

Per chi protegge il proprio sito (di sviluppo) dall'accesso pubblico, l'autenticazione HTTP può essere la causa del mancato funzionamento di WP Cron.

Nel caso possa essere utile a qualcuno, ecco la lista delle cose che ho fatto prima di identificare e comprendere i requisiti di WP Cron:

  • Ho notato che gli eventi erano correttamente schedulati e potevano essere eseguiti utilizzando WP-CLI.
  • E ho anche notato che accedendo a /wp-cron.php?doing_wp_cron tramite browser venivano effettivamente attivate le esecuzioni, come suggerito ad esempio in 13625.
  • La documentazione ufficiale è stata letta.
  • Mi sono assicurato che DISABLE_WP_CRON non fosse impostato.
  • E ho appreso che ALTERNATE_WP_CRON era una soluzione alternativa efficace, seppur insoddisfacente.
  • Per escludere bug di regressione, ho provato a installare un paio di versioni precedenti di WordPress.
  • Tutti i plugin sono stati disabilitati e il tema è stato cambiato con quello predefinito, per isolare il problema.
  • Alcuni menzionavano il termine loopback, ma poiché non ricevevo errori o avvisi correlati, l'ho considerato irrilevante.
  • Infine, ho trovato una domanda con una risposta che spiegava effettivamente come eseguire il debug di cron.
  • Dopo aver collegato Xdebug a wp_cron(), ho potuto vedere che l'esecuzione finiva in wp_remote_post(), che chiaramente falliva.

Sapendo cosa cercare, ho trovato questo ottimo articolo sulle cause dei problemi di WP Cron di Jeff Starr. Alla fine dell'articolo, egli rimanda al suo plugin wp-cron-http-auth.

17 giu 2020 10:37:19
1

Verifica che DISABLE_WP_CRON non sia impostato nel tuo file di configurazione.

Se non è quello il problema, prova a disabilitare tutti i plugin (tranne core control - anche se consiglio wp-crontrol) e verifica se i lavori di base funzionano. Se funzionano, significa che c'è un'interferenza da parte di qualche plugin.

Allo stesso modo, prova a passare a un tema standard come twentysomething.

Se nessuna di queste soluzioni fa differenza, è probabile che si tratti di un problema di hosting.

4 apr 2013 20:19:23
Commenti

Non ho impostato DISABLE_WP_CRON nel mio wp-config.php, proverò altre cose e tornerò più tardi

Mike Madern Mike Madern
9 apr 2013 16:07:21
0

Controlla qualsiasi plugin che nasconda WordPress.

Come verificare se questo è il problema?

  1. Naviga su http(s)://yoursite.com/wp-cron.php Dovresti vedere una pagina vuota. Completamente vuota.
  2. Inoltre, nel gestore dei cron job dovresti vedere un orario sotto "Prossima esecuzione": Cron job programmato - se wp-cron.php funziona correttamente (non solo il testo "In coda" - ma un orario specifico - per alcune voci "In coda" è accettabile in certi casi, ma se è l'unica cosa che vedi -> il tuo cron non funziona.)

+1. Non fidarti di alcun plugin che "verifica se il cron funziona" - ad esempio, il plugin WP Cron status checker ha mostrato che il cron funzionava. Ma in realtà non era così. Qualunque cosa mostri - credi ai tuoi occhi e non a questo plugin!

Conclusione: Se ricevi un errore 404 - allora disattiva a) non solo i plugin di caching come suggerito da altri b) ma anche qualsiasi plugin che nasconda WordPress.

16 apr 2019 00:45:30