WP Cron nie wykonuje się po upływie czasu

16

Cel

Chcę użyć wp_schedule_single_event( )do wykonania pojedynczego zdarzenia, które wyśle ​​mi wiadomość e-mail 8 minut po przesłaniu formularza przez użytkownika.

Problem

W moim jest następujący kod 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 ) );
}

Do wywołania służy następujący kod schedule-event:

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

Po odczekaniu ponad 8 minut w mojej skrzynce odbiorczej nie było wiadomości e-mail.

Co próbowałem

Dzięki wtyczce Core Control można zobaczyć, które zadania cron są zaplanowane.

Ekran kontroli rdzenia

Po kilku zmianach udało mi się je całkowicie poprawić, a lepiej, gdy kliknę „Uruchom teraz”, faktycznie otrzymuję wiadomość e-mail w mojej skrzynce odbiorczej.

Ale dlaczego cron nie wykonuje się, gdy odwiedzam moją stronę po 8 minutach. Co może być nie tak z tym kodem? Muszę powiedzieć, że po raz pierwszy używam WP Cron.

Próbowałem więcej

Po komentarzu id vancodera postanowiłem sprawdzić, czy kod działa, jeśli wstawię następujący kod bezpośrednio do 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'];
  }
}

Minusem tego kodu jest to, że użytkownik musi przejść do innej strony, zanim ten kod zostanie wykonany. Ale z drugiej strony to też nie działa, więc nie byłby to mój pierwszy problem ...

Mike Madern
źródło
1
Gdzie i jak jest schedule_event( $_SESSION['insert_id'] );zwolniony?
vancoder
Krótki kod zawiera osobny plik (z formularzem w nim) na stronie, gdy formularz jest publikowany, strona ładuje się ponownie, ten sam plik wykonuje następnie schedule_event( ), powiedzmy na górze dołączonego pliku załadowanego przez shortcode.
Mike Madern
Czy jakieś crony działają? wp_version_check itp?
vancoder
Nie dostałem żadnych kolesi do pracy. Co może być tego przyczyną?
Mike Madern
Aby potwierdzić - nawet podstawowe zadania CRON-a zawodzą?
vancoder

Odpowiedzi:

8

Najpierw możesz potwierdzić, że nie masz włączonych żadnych wtyczek buforujących? Wtyczki buforujące mogą zakłócać zadania crona, ponieważ odwiedzającym nie jest wyświetlana strona aktywna, ale wersja strony z pamięci podręcznej.

Jeśli masz włączoną wtyczkę buforującą, możesz wybrać jedną ze stron, dodać wyjątek do ustawień wtyczki buforującej dla tej strony, aby nigdy nie była buforowana.

Następnie musisz ręcznie utworzyć zadanie cron (używając cpanel, jeśli korzystasz ze współdzielonego środowiska hostingowego lub z terminala, jeśli jest to serwer VPS / dedykowany), który będzie odwiedzał tę stronę co kilka minut.

Mam nadzieję że to pomogło!

WPMU-DEV Ari
źródło
Mam włączoną wtyczkę buforowania! Dokładnie W3 Total Cache
Mike Madern
14

Po pierwsze, zdefiniuj swoje niestandardowe harmonogramy zadań cron.

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

Musisz zdecydować, gdzie i kiedy faktycznie zaplanować wydarzenie.

Oto tylko przykładowy fragment kodu, który wywołuje metodę niestandardowej klasy:

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

Oto kod, który faktycznie planuje wydarzenie:

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

Teraz wystarczy zadzwonić pod nazwę niestandardowego zadania cron. W tym przykładzie nazwa zadania cron to custom_imap_import.

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

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

W tym przykładzie $this->do_imap_import();jest wywoływany co 30 minut (zakładając, że masz wystarczający ruch do swojej witryny).


Notatki

Wymaga wizyty na stronie, aby twój cron mógł odpalić w odpowiednim czasie.

Przykład: jeśli zaplanowałeś zadanie w 30-minutowych odstępach, ale nikt nie odwiedził Twojej witryny przez 4 godziny, twoje zadanie cron nie zostanie zwolnione, dopóki ten gość nie pojawi się na Twojej stronie 4 godziny później. Jeśli naprawdę potrzebujesz, aby Twoje zadanie było uruchamiane co 30 minut, zalecamy skonfigurowanie legalnej pracy crona za pośrednictwem usługodawcy hostingowego, aby odwiedzał twoją stronę internetową w pożądanych odstępach czasu.

Zadania cron WordPress nie spowalniają Twojej witryny!

Być może zastanawiasz się, co jeśli wykonanie skryptu cron zajmuje dużo czasu, odwiedzający będą musieli poczekać, aż skrypt zostanie wykonany. Nie! Jak to możliwe? Jeśli spojrzysz na wp-cron.phpplik, znajdziesz linię

ignore_user_abort(true);

Jest to php.inikonfiguracja, która powoduje, że jeśli przestaniesz ładować witrynę / skrypt, skrypt nie przestanie działać.

Jeśli spojrzysz na wp-includes/cron.phpplik, znajdziesz taką linię:

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

Oznacza to, że WordPress będzie czekać tylko 0,01 sekundy do wyzwalania wykonanie to będzie przerwać, ale jak masz ustawione ignore_user_abortdo trueskryptu będzie wykonywany. Ta funkcja jest ogromną zaletą do wykonywania dużych skryptów w zadaniach cron WordPress.

Dostępne funkcje pomocy:

Michael Ecklund
źródło
6
Jest to niezwykle kompleksowa odpowiedź, która, o ile widzę, nie odnosi się do rzeczywistego pytania - dlatego wszystkie zaplanowane zadania (w tym zadania podstawowe) zawodzą.
vancoder
Ta odpowiedź ma poprowadzić użytkownika we właściwym kierunku, aby poprawnie zrozumieć i zaplanować zadania cron WordPress.
Michael Ecklund
4
To z pewnością pomogło mi dobrze zrozumieć harmonogramy cronów za pomocą WordPress
Mike Madern,
2
Michael, powinieneś częściej odpowiadać. Świetny +1
kaiser
1
Myślę, że WP_Cronużywa GMT pod maską, podobnie jak reszta WP, więc lepiej zaplanować pierwsze wydarzenie time()zamiast current_time().
Ian Dunn
3

WordPress Cron pozwala zaplanować zadania, ale zostaną one wykonane tylko wtedy, gdy zostanie wysłane żądanie do witryny. Przy każdym żądaniu otrzymywanym przez WordPress sprawdzi, czy istnieją zadania cron do przetworzenia, a jeśli tak, odpala żądanie /wp-cron.php?doing_wp_cronasynchronicznie w celu przetworzenia zadania. Jeśli zaplanowane uruchomienie zadania przebiega bez żądania, proces cron nie zostanie uruchomiony.

Ponieważ możesz zobaczyć i uruchomić zaplanowane zadania, możliwe, że nie ma żądań, które wyzwalają uruchomienie zadania cron, zwłaszcza jeśli używasz wtyczki buforowania. Najlepszą opcją przeniesienia tego do bardziej regularnego harmonogramu jest wyłączenie domyślnego sprawdzania w WordPress i korzystanie z niego crontab.

Najpierw wyłącz domyślne sprawdzanie (które może trochę pomóc w wydajności po stronie klienta), dodaj następujące elementy do wp-config.php:

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

Następnie utwórz zadanie pobierania wp-cron.phpstrony raz na minutę w celu przetworzenia dowolnego zadania z zaplecza, z poziomu wiersza poleceń wprowadź, crontab -ea następnie dodaj wiersz, który wygląda następująco:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
podwójne rozwiązywanie problemów
źródło
2
Jeśli nie podasz wartości do robi_wp_cron, istnieje duże prawdopodobieństwo, że zadania będą czasami wykonywane dwukrotnie. Użyj, doing_wp_cron=$(date +\%s.\%N)aby temu zapobiec.
Alexander Garden
0

Sprawdź, czy DISABLE_WP_CRON nie jest ustawiony w twojej konfiguracji.

W przeciwnym razie spróbuj wyłączyć wszystkie wtyczki (oprócz kontroli rdzenia - chociaż użyłbym wp-crontrol) i sprawdź, czy twoje podstawowe zadania działają. Jeśli tak, to gdzieś występują zakłócenia wtyczek.

Podobnie spróbuj przełączyć się na standardowy motyw dwudziestokrotnie.

Jeśli żaden z nich nie robi żadnej różnicy, istnieje prawdopodobieństwo, że jest to problem z hostingiem.

Vancoder
źródło
Nie DISABLE_WP_CRONustawiłem się wp-config.php, spróbuję więcej rzeczy i wrócę później
Mike Madern,
0

Sprawdź dowolną wtyczkę, która ukrywa Wordpress.

Jak sprawdzić, czy to jest problem?

  1. Przejdź do http (s): //twojastrona.com/wp-cron.php Powinieneś zobaczyć pustą stronę. Zupełnie pusty.
  2. Poza tym musisz zobaczyć w menedżerze zadań crona czas pod „Następnym wykonaniem”: Zaplanowane zadanie Cron - jeśli wp-cron.php działa poprawnie (nie tylko tekst „W kolejce” - ale dany czas - dla niektórych wpisów „W kolejce” jest czasem OK, ale jeśli jest to jedyna rzecz widzisz -> twój cron nie działa.)

+1. Nie wierz w żadne wtyczki, które „sprawdzają, czy cron działa” - np. Wtyczka sprawdzania statusu WP Cron wykazała, że ​​cron działa. Ale tak się nie stało. Cokolwiek to pokazuje - wierz swoim oczom, a nie tej wtyczce!

Wniosek: jeśli jest to błąd 404 - wyłącz a) nie tylko buforowanie wtyczek, jak sugerują inni b), ale także wszelkie wtyczki, które ukrywają Wordpress.

Peter Cz
źródło