web-dev-qa-db-fra.com

WP Cron ne s'exécute pas à la fin du temps

Le but

Je souhaite utiliser wp_schedule_single_event( ) pour exécuter un événement unique qui m'envoie un courrier électronique 8 minutes après que l'utilisateur a envoyé un formulaire.

Le problème

Le code suivant est dans mon 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 ) );
}

Et le code suivant est utilisé pour appeler schedule-event:

schedule_event( $_SESSION['insert_id'] ); // the $_SESSION var contains an INT

Après avoir attendu plus de 8 minutes, il n'y avait pas d'e-mail dans ma boîte de réception.

Ce que j'ai essayé

Avec le plugin Core Control , il est possible de voir quelles tâches cron sont planifiées.

Core Control screen

Après quelques modifications, j'ai réussi à les corriger, et mieux encore, lorsque je clique sur "Run Now", je reçois un message électronique dans ma boîte de réception.

Mais pourquoi le cron ne s'exécute pas lorsque je visite mon site après 8 minutes. Quel est le problème avec ce code? Je dois dire que c'est la première fois que j'utilise WP Cron.

J'ai essayé plus

Après le commentaire de vancoder id a décidé de vérifier si le code fonctionne si je mets le code suivant directement dans le 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'];
  }
}

L'inconvénient de ce code est que l'utilisateur doit accéder à une autre page avant que ce code ne soit exécuté. Mais de l’autre côté, cela ne marche pas non plus, alors ce ne serait pas mon premier problème….

16
Mike Madern

D'abord, pouvez-vous s'il vous plaît confirmer que vous n'avez aucun plugin de cache activé? Les plugins de mise en cache peuvent interférer avec les tâches cron car vos visiteurs ne reçoivent pas une page en direct mais une version mise en cache de votre page.

Si un plug-in de mise en cache est activé, vous pouvez choisir l'une de vos pages, ajouter une exclussion aux paramètres de votre plug-in de mise en cache pour cette page afin qu'elle ne soit jamais mise en cache.

Ensuite, vous devrez créer manuellement une tâche cron (en utilisant cpanel si vous êtes sur un environnement d'hébergement partagé ou à partir du terminal s'il s'agit d'un serveur VPS/dédié) qui visitera cette page toutes les quelques minutes.

J'espère que ça aide!

8
WPMU-DEV Ari

Tout d’abord, définissez vos plannings de tâches cron personnalisés.

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

public function cron_schedules($schedules){
    $prefix = 'cron_';// Avoid conflict with other crons. Example Reference: cron_30_mins
    $schedule_options = array(
        '30_mins' => array(
            'display' => '30 Minutes',
            'interval' => '1800'
        ),
        '1_hours' => array(
            'display' => 'Hour',
            'interval' => '3600'
        ),
        '2_hours' => array(
            'display' => '2 Hours',
            'interval' => '7200'
        )
    );
    /* Add each custom schedule into the cron job system. */
    foreach($schedule_options as $schedule_key => $schedule){
        $schedules[$prefix.$schedule_key] = array(
            'interval' => $schedule['interval'],
            'display' => __('Every '.$schedule['display'])
        );
     }
     return $schedules;
}

Vous devez décider où et quand programmer réellement l'événement.

Voici juste un exemple de code qui appelle la méthode de classe personnalisée:

$schedule = $this->schedule_task(array(
    'timestamp' => current_time('timestamp'), // Determine when to schedule the task.
    'recurrence' => 'cron_30_mins',// Pick one of the schedules set earlier.
    'hook' => 'custom_imap_import'// Set the name of your cron task.
));

Voici le code qui planifie réellement l'événement:

private function schedule_task($task){
    /* Must have task information. */
    if(!$task){
        return false;
    }
    /* Set list of required task keys. */
    $required_keys = array(
        'timestamp',
        'recurrence',
        'hook'
    );
    /* Verify the necessary task information exists. */
    $missing_keys = array();
    foreach($required_keys as $key){
        if(!array_key_exists($key, $task)){
            $missing_keys[] = $key;
        }
    }
    /* Check for missing keys. */
    if(!empty($missing_keys)){
        return false;
    }
    /* Task must not already be scheduled. */
    if(wp_next_scheduled($task['hook'])){
        wp_clear_scheduled_hook($task['hook']);
    }
    /* Schedule the task to run. */
    wp_schedule_event($task['timestamp'], $task['recurrence'], $task['hook']);
    return true;
}

Il ne vous reste plus qu'à appeler le nom de votre tâche périodique personnalisée. Dans cet exemple, le nom de la tâche périodique est custom_imap_import.

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

public function do_imap_import(){
    // .... Do stuff when cron is fired ....
}

Ainsi, dans cet exemple, $this->do_imap_import(); est appelée toutes les 30 minutes (en supposant que le trafic sur votre site Web soit suffisant).


Remarques

Nécessite une visite de la page pour que votre cron puisse se déclencher aux heures appropriées.

Exemple: Si vous planifiez une tâche à 30 minutes d'intervalle, mais que personne ne visite votre site pendant 4 heures, votre tâche cron ne sera déclenchée que lorsque ce visiteur viendra sur votre site 4 heures plus tard. Si vous avez vraiment besoin que votre tâche soit renvoyée toutes les 30 minutes, il est conseillé de configurer une tâche cron légitime via votre fournisseur d’hébergement Web pour visiter votre site Web aux intervalles souhaités.

Les travaux cron de WordPress ne ralentissent pas votre site Web!

Vous pensez peut-être que si l'exécution du script cron prend beaucoup de temps, les visiteurs devront-ils attendre que le script soit exécuté. Nan! Comment cela peut-il être possible? Si vous regardez le fichier wp-cron.php, vous trouverez une ligne

ignore_user_abort(true);

C'est une configuration php.ini qui définit que si vous arrêtez de charger le site/script, le script ne s'arrêtera pas de s'exécuter.

Si vous regardez le fichier wp-includes/cron.php, vous trouverez une ligne comme celle-ci:

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

Cela signifie que WordPress attendra seulement 0.01 seconde pour déclencher l'exécution, puis il abandonnera, mais comme vous avez défini ignore_user_abort sur true, le script sera exécuté. Cette fonctionnalité est un avantage énorme pour l'exécution de scripts volumineux dans les tâches cron de WordPress.

Fonctions disponibles pour l'aide:

14
Michael Ecklund

WordPress Cron vous permet de planifier des tâches, mais celles-ci ne seront exécutées que si une demande est faite au site. Pour chaque demande reçue par WordPress, il vérifiera s'il existe des tâches cron à traiter et, le cas échéant, déclenche une demande de /wp-cron.php?doing_wp_cron de manière asynchrone pour traiter la tâche. Si le démarrage planifié d'un travail se passe sans demande, le processus cron ne sera pas démarré.

Comme vous pouvez voir et exécuter vos travaux planifiés, il est possible qu'aucune demande ne déclenche le démarrage du travail cron, en particulier si vous utilisez un plug-in de mise en cache. La meilleure option pour décharger cela dans un calendrier plus régulier consiste à désactiver la vérification par défaut dans WordPress et à utiliser crontab.

Tout d’abord pour désactiver la vérification par défaut (ce qui peut aider un peu aux performances côté client), ajoutez ce qui suit à wp-config.php:

// Disable default check for WordPress cron jobs on page loads
define( 'DISABLE_WP_CRON', true );

Ensuite, vous créez une tâche pour extraire la page wp-cron.php une fois par minute afin de traiter les tâches dorsales. À partir de la ligne de commande, entrez crontab -e, puis ajoutez une ligne semblable à celle-ci:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
3
doublesharp

Vérifiez tout plugin qui cache Wordpress.

Comment voir si c'est le problème?

  1. Accédez à http (s): //votresite.com/wp-cron.php. Vous devriez voir une page vide. Un complètement vide.
  2. De plus, vous devez voir dans un gestionnaire de tâches cron une heure sous "Prochaine exécution":  Cron job scheduled - if wp-cron.php works properly  (non seulement le texte "En file d'attente" - mais une heure donnée - pour certaines entrées "En file d'attente" est parfois OK, mais si c'est la seule chose que vous voyez -> votre cron ne fonctionne pas.)

+1 Ne croyez pas les plugins qui "vérifient si cron fonctionne" - par exemple. WP Le plug-in de vérification d'état de Cron a montré que Cron fonctionne. Mais en fait, ce n’est pas le cas.  Whatever it shows - believe your eyes and not this plugin! 

Conclusion: s’il s’agit d’une erreur 404, désactivez a) non seulement la mise en cache des plugins, comme le suggèrent b), mais aussi les plugins masquant Wordpress.

0
Peter Cz

Vérifiez que DISABLE_WP_CRON n'est pas défini dans votre configuration.

En cas d'échec, essayez de désactiver tous les plug-in (à l'exception du contrôle de base - bien que j'utilise wp-crontrol) et voyez si vos travaux de base fonctionnent. S'ils le font, vous rencontrez des interférences de plug-ins quelque part.

De même, essayez de passer à un thème standard de la vingtaine d'années.

Si rien de tout cela ne fait la différence, il y a de fortes chances que ce soit un problème d'hébergement.

0
vancoder