WP Cron wird nach Ablauf der Zeit nicht ausgeführt

16

Das Ziel

Ich möchte wp_schedule_single_event( )ein einzelnes Ereignis ausführen, das mir 8 Minuten nach dem Absenden eines Formulars durch den Benutzer eine E-Mail sendet.

Die Angelegenheit

Der folgende Code ist in meinem 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 ) );
}

Und der folgende Code wird zum Aufrufen verwendet schedule-event:

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

Nach einer Wartezeit von mehr als 8 Minuten befand sich keine E-Mail in meinem Posteingang.

Was ich versucht habe

Mit dem Plugin Core Control ist es möglich zu sehen, welche Cronjobs geplant sind.

Core Control-Bildschirm

Nach ein paar Änderungen habe ich es geschafft, sie richtig zu machen, und besser, wenn ich auf "Jetzt ausführen" drücke, bekomme ich tatsächlich eine E-Mail in meinem Posteingang.

Aber warum werden die Crons nicht ausgeführt, wenn ich meine Site nach 8 Minuten besuche? Was ist möglicherweise falsch an diesem Code? Ich muss sagen, dass ich WP Cron zum ersten Mal benutze.

Ich habe mehr versucht

Nach dem Kommentar von Vancoder ID beschlossen, zu testen, ob der Code funktioniert, wenn ich den folgenden Code direkt in das 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'];
  }
}

Der Nachteil dieses Codes ist, dass der Benutzer eine andere Seite aufrufen muss, bevor dieser Code ausgeführt wird. Aber auf der anderen Seite funktioniert das auch nicht, das wäre nicht meine erste Ausgabe ...

Mike Madern
quelle
1
Wo und wie wird schedule_event( $_SESSION['insert_id'] );gefeuert?
Vancoder
Ein Shortcode enthält eine separate Datei (mit einem Formular darin) auf einer Seite. Wenn dieses Formular veröffentlicht wird, lädt die Seite erneut, und dieselbe Datei führt dann die schedule_event( )Datei aus, beispielsweise über der vom Shortcode geladenen enthaltenen Datei.
Mike Madern
Haben alle crons Arbeit? wp_version_check etc?
Vancoder
Ich habe keine Crons zum Arbeiten gebracht. Woran könnte das liegen?
Mike Madern
Zur Bestätigung - selbst Core-Cron-Jobs schlagen fehl?
Vancoder

Antworten:

8

Kannst du bitte zuerst bestätigen, dass keine Caching-Plugins aktiviert sind? Caching-Plugins können Cron-Jobs stören, da Ihren Besuchern keine Live-Seite, sondern eine zwischengespeicherte Version Ihrer Seite bereitgestellt wird.

Wenn Sie ein Caching-Plugin aktiviert haben, können Sie eine Ihrer Seiten auswählen und den Einstellungen Ihres Caching-Plugins für diese Seite einen Ausschluss hinzufügen, damit es niemals zwischengespeichert wird.

Dann müssen Sie manuell einen Cron-Job erstellen (mit cpanel, wenn Sie sich in einer gemeinsam genutzten Hosting-Umgebung befinden, oder vom Terminal aus, wenn es sich um einen VPS / dedizierten Server handelt), der diese Seite alle paar Minuten aufruft.

Ich hoffe das hilft!

WPMU-DEV Ari
quelle
Ich habe ein Caching-Plugin aktiviert! W3 Total Cache um genau zu sein
Mike Madern
14

Definieren Sie zunächst Ihre benutzerdefinierten Zeitpläne für Cron-Jobs.

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;
}

Sie müssen entscheiden, wo und wann die Veranstaltung stattfinden soll.

Hier ist nur ein Codebeispiel, mit dem eine benutzerdefinierte Klassenmethode aufgerufen wird:

$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.
));

Hier ist der Code, der das Ereignis tatsächlich plant:

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;
}

Jetzt müssen Sie nur noch den Namen Ihrer benutzerdefinierten Cron-Aufgabe aufrufen. In diesem Beispiel lautet der Name der Cron-Aufgabe custom_imap_import.

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

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

In diesem Beispiel wird $this->do_imap_import();also alle 30 Minuten aufgerufen (vorausgesetzt, Sie haben genügend Zugriffe auf Ihre Website).


Anmerkungen

Erfordert einen Seitenbesuch, damit Ihr Cron zum richtigen Zeitpunkt ausgelöst wird.

Beispiel: Wenn Sie eine Aufgabe in 30-Minuten-Intervallen geplant haben, aber 4 Stunden lang niemand Ihre Site besucht, wird Ihr Cron-Job erst dann ausgelöst, wenn dieser Besucher 4 Stunden später zu Ihrer Site kommt. Wenn Ihre Aufgabe wirklich alle 30 Minuten ausgeführt werden muss, wird empfohlen, einen legitimen Cron-Job über Ihren Webhosting-Anbieter einzurichten, um Ihre Website in den gewünschten Abständen zu besuchen.

WordPress-Cron-Jobs machen Ihre Website nicht langsam!

Vielleicht überlegen Sie, was, wenn die Ausführung des Cron-Skripts lange dauert, die Besucher warten müssen, bis das Skript ausgeführt wird. Nee! Wie kann das möglich sein? Wenn Sie sich die wp-cron.phpDatei ansehen , finden Sie eine Zeile

ignore_user_abort(true);

In dieser php.iniKonfiguration wird festgelegt, dass das Skript nicht mehr ausgeführt wird, wenn Sie das Laden der Site / des Skripts beenden.

Wenn Sie sich die wp-includes/cron.phpDatei ansehen, finden Sie eine Zeile wie diese:

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

Das bedeutet, dass WordPress nur 0,01 Sekunden auf das Auslösen der Ausführung wartet und dann abgebrochen wird, aber wie Sie es eingestellt haben ignore_user_abort, wird truedas Skript ausgeführt. Diese Funktionalität ist ein großer Vorteil, um große Skripte in WordPress-Cron-Jobs auszuführen.

Für die Hilfe verfügbare Funktionen:

Michael Ecklund
quelle
6
Dies ist eine bemerkenswert umfassende Antwort, die meines Erachtens die eigentliche Frage nicht beantwortet - weshalb alle geplanten Aufgaben (einschließlich der Kernaufgaben) fehlschlagen.
Vancoder
Diese Antwort soll den Benutzer in die richtige Richtung führen, um WordPress-Cron-Aufgaben richtig zu verstehen und zu planen.
Michael Ecklund
4
Dies hat mir sehr geholfen, die Cron-Zeitpläne mit WordPress zu verstehen
Mike Madern
2
Michael, du solltest öfter antworten. Great one +1
Kaiser
1
Ich denke, es WP_Cronwird GMT unter der Haube verwendet, so wie der Rest des WP, also ist es besser, das erste Event zu planen, time()anstatt current_time().
Ian Dunn
3

Mit WordPress Cron können Sie Aufgaben planen, die jedoch nur ausgeführt werden, wenn eine Anfrage an die Site gestellt wird. Bei jeder Anfrage, die WordPress erhält, wird geprüft, ob Cron-Jobs zu verarbeiten sind. In diesem Fall wird eine Anfrage zur /wp-cron.php?doing_wp_cronasynchronen Verarbeitung des Jobs ausgelöst. Wenn der geplante Start eines Jobs ohne Anforderung verstrichen ist, wird der Cron-Prozess nicht gestartet.

Da Sie Ihre geplanten Jobs anzeigen und ausführen können, gibt es möglicherweise keine Anforderungen, die den Start des Cron-Jobs auslösen, insbesondere wenn Sie ein Caching-Plugin verwenden. Die beste Möglichkeit, dies in einen regelmäßigeren Zeitplan zu verschieben, besteht darin, die Standardprüfung in WordPress zu deaktivieren und zu verwenden crontab.

Fügen Sie Folgendes hinzu, um die Standardprüfung zu deaktivieren (was die Leistung auf der Clientseite etwas verbessern kann) wp-config.php:

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

Als Nächstes erstellen Sie eine Aufgabe, um die wp-cron.phpSeite einmal pro Minute abzurufen und alle Jobs im Back-End zu verarbeiten. Geben Sie dazu über die Befehlszeile crontab -eFolgendes ein und fügen Sie eine Zeile hinzu, die wie folgt aussieht:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
Doublesharp
quelle
2
Wenn Sie doing_wp_cron keinen Wert zuweisen, werden Jobs mit hoher Wahrscheinlichkeit manchmal zweimal ausgeführt. Verwenden Sie doing_wp_cron=$(date +\%s.\%N), um das zu verhindern.
Alexander Garden
0

Stellen Sie sicher, dass DISABLE_WP_CRON nicht in Ihrer Konfiguration festgelegt ist.

Andernfalls deaktivieren Sie alle Plugins (außer der Kernsteuerung - obwohl ich wp-crontrol verwenden würde) und prüfen Sie, ob Ihre Kernaufträge funktionieren. In diesem Fall tritt irgendwo eine Plug-in-Störung auf.

Versuchen Sie in ähnlicher Weise, zu einem Standardthema für 20-Jährige zu wechseln.

Wenn keines davon einen Unterschied macht, ist es wahrscheinlich ein Hosting-Problem.

Vancoder
quelle
Ich habe nicht DISABLE_WP_CRONin meinem festgelegt wp-config.php, ich werde mehr Dinge versuchen und später wiederkommen
Mike Madern
0

Überprüfen Sie alle Plugins, die Wordpress verbergen.

Wie kann man sehen, ob dies das Problem ist?

  1. Navigieren Sie zu http (s): //yoursite.com/wp-cron.php. Sie sollten eine leere Seite sehen. Eine völlig leere.
  2. Außerdem müssen Sie in einem Cron Job Manager eine Zeit unter "Nächste Ausführung" sehen: Cron-Job geplant - wenn wp-cron.php richtig funktioniert (Nicht nur der Text "In Warteschlange" - sondern eine bestimmte Zeit - für einige Einträge ist "In Warteschlange" manchmal in Ordnung, aber wenn es das einzige ist du siehst -> dein cron funktioniert nicht.)

+1. Glauben Sie keinen Plugins, die "prüfen, ob cron funktioniert" - zB das WP Cron Status Checker Plugin hat gezeigt, dass cron funktioniert. Tatsächlich aber nicht. Was auch immer es zeigt - glauben Sie Ihren Augen und nicht diesem Plugin!

Fazit: Wenn es sich um einen 404-Fehler handelt, deaktivieren Sie a) nicht nur das Zwischenspeichern von Plugins, wie von anderen empfohlen, sondern auch alle Plugins, die Wordpress verbergen.

Peter Cz
quelle