WP Cron Tidak Menjalankan Ketika Waktu Berlalu

16

Target

Saya ingin menggunakan wp_schedule_single_event( )untuk menjalankan satu peristiwa yang mengirimi saya email 8 menit setelah pengguna mengirimkan formulir.

Masalah

Kode berikut ada di saya 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 ) );
}

Dan kode berikut digunakan untuk memanggil schedule-event:

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

Setelah menunggu lebih dari 8 menit, tidak ada email di inbox saya.

Apa yang saya coba

Dengan plugin Core Control , Anda dapat melihat jadwal tugas cron yang dijadwalkan.

Layar Kontrol Inti

Setelah beberapa perubahan saya berhasil membuatnya cukup benar, dan lebih baik, ketika saya menekan "Jalankan Sekarang", saya benar-benar mendapatkan email di kotak masuk saya.

Tetapi mengapa cron's tidak mengeksekusi ketika saya mengunjungi situs saya setelah 8 menit. Apa yang mungkin salah dengan kode ini? Saya harus mengatakan bahwa ini adalah pertama kalinya saya menggunakan WP Cron.

Saya mencoba lebih banyak

Setelah komentar vancoder id memutuskan untuk menguji apakah kodenya berfungsi jika saya langsung memasukkan kode berikut di 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'];
  }
}

Kelemahan dari kode ini adalah, pengguna harus pergi ke halaman lain sebelum kode ini dieksekusi. Tapi di sisi lain, ini juga tidak berfungsi sehingga tidak akan menjadi masalah pertamaku ...

Mike Madern
sumber
1
Di mana dan bagaimana schedule_event( $_SESSION['insert_id'] );dipecat?
vancoder
Kode pendek termasuk file terpisah (dengan formulir di dalamnya) di halaman, ketika formulir itu diposting halaman reload, file yang sama kemudian menjalankan schedule_event( ), katakanlah di atas file yang disertakan dimuat oleh kode pendek.
Mike Madern
Apakah ada crons yang berfungsi? wp_version_check dll?
vancoder
Saya tidak mendapatkan apa crons bekerja. Apa yang bisa menjadi masalah itu?
Mike Madern
Untuk mengkonfirmasi - bahkan pekerjaan cron inti gagal?
vancoder

Jawaban:

8

Pertama-tama bisakah Anda mengonfirmasi bahwa Anda tidak mengaktifkan plugin caching? Plugin caching dapat mengganggu pekerjaan cron karena pengunjung Anda tidak dilayani halaman langsung tetapi versi cache halaman Anda.

Jika Anda mengaktifkan plugin caching, Anda dapat memilih salah satu halaman Anda, menambahkan pengecualian ke pengaturan plugin caching Anda untuk halaman itu sehingga tidak pernah di-cache.

Maka Anda harus secara manual membuat pekerjaan cron (menggunakan cpanel jika Anda berada di lingkungan hosting bersama atau dari terminal jika itu adalah VPS / server khusus) yang akan mengunjungi halaman itu setiap beberapa menit.

Saya harap itu membantu!

WPMU-DEV Ari
sumber
Saya mengaktifkan plugin caching! W3 Total Cache tepatnya
Mike Madern
14

Pertama, tentukan jadwal pekerjaan cron khusus Anda.

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

Anda harus memutuskan di mana dan kapan harus menjadwalkan acara.

Berikut ini hanya potongan contoh kode, yang melakukan panggilan ke metode kelas khusus:

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

Berikut adalah kode yang sebenarnya menjadwalkan acara:

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

Sekarang, yang perlu Anda lakukan adalah menelepon ke nama tugas cron kustom Anda. Dalam contoh ini nama tugas cron adalah custom_imap_import.

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

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

Jadi, dalam contoh ini, $this->do_imap_import();dipanggil setiap 30 menit (dengan asumsi Anda memiliki lalu lintas yang cukup ke situs web Anda).


Catatan

Membutuhkan kunjungan halaman agar cron Anda dapat dijalankan pada waktu yang tepat.

Contoh: Jika Anda menjadwalkan tugas pada interval 30 menit, tetapi tidak ada yang mengunjungi situs Anda selama 4 jam, pekerjaan cron Anda tidak akan dipecat sampai pengunjung itu datang ke situs Anda 4 jam kemudian. Jika Anda benar-benar benar-benar membutuhkan tugas Anda dipecat setiap 30 menit, maka disarankan untuk menyiapkan pekerjaan cron yang sah melalui penyedia hosting web Anda untuk mengunjungi situs web Anda pada interval yang diinginkan.

Pekerjaan cron WordPress tidak membuat situs web Anda lambat!

Mungkin Anda berpikir bagaimana jika skrip-cron membutuhkan waktu lama untuk dieksekusi, apakah para pengunjung harus menunggu sampai skrip dijalankan. Nggak! Bagaimana itu bisa terjadi? Jika Anda melihat wp-cron.phpfile Anda akan menemukan garis

ignore_user_abort(true);

Ini adalah php.inikonfigurasi yang menetapkan bahwa jika Anda berhenti memuat situs / skrip, skrip tidak akan berhenti mengeksekusi.

Jika Anda melihat wp-includes/cron.phpfile Anda akan menemukan garis seperti ini:

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

Itu berarti WordPress akan menunggu hanya 0,01 detik untuk memicu eksekusi maka akan membatalkan tetapi karena Anda telah menetapkan ignore_user_abortuntuk truescript akan mengeksekusi. Fungsi ini adalah keuntungan besar untuk mengeksekusi skrip besar dalam pekerjaan cron WordPress.

Fungsi tersedia untuk bantuan:

Michael Ecklund
sumber
6
Ini adalah respons yang sangat komprehensif, yang sejauh yang dapat saya lihat, gagal menjawab pertanyaan aktual - yang mengapa semua tugas terjadwal (termasuk tugas inti) gagal.
vancoder
Jawaban ini adalah untuk memandu pengguna ke arah yang benar untuk memahami dan menjadwalkan tugas-tugas cron WordPress dengan benar.
Michael Ecklund
4
Ini jelas membantu saya memahami jadwal cron dengan WordPress
Mike Madern
2
Michael, Anda harus menjawab lebih sering. Hebat +1 + 1
kaiser
1
Saya pikir WP_Cronmenggunakan GMT di bawah tenda, seperti sisa WP, jadi akan lebih baik untuk menjadwalkan acara pertama di time()bukan current_time().
Ian Dunn
3

WordPress Cron memungkinkan Anda untuk menjadwalkan tugas, tetapi mereka hanya akan mengeksekusi jika ada permintaan yang dibuat ke situs. Untuk setiap permintaan yang diterima WordPress, akan memeriksa untuk melihat apakah ada pekerjaan cron yang harus diproses, dan jika demikian, permintaan akan /wp-cron.php?doing_wp_crondisinkronkan untuk memproses pekerjaan secara asinkron. Jika mulai dijadwalkan pekerjaan berlalu tanpa permintaan, maka proses cron tidak akan dimulai.

Karena Anda dapat melihat dan menjalankan pekerjaan terjadwal Anda, ada kemungkinan bahwa tidak ada permintaan yang memicu pekerjaan cron untuk memulai, terutama jika Anda menggunakan plugin caching. Opsi terbaik untuk melepas ini ke jadwal yang lebih teratur adalah dengan menonaktifkan pemeriksaan default di WordPress dan menggunakannya crontab.

Pertama untuk menonaktifkan pemeriksaan default (yang dapat sedikit membantu dengan kinerja sisi klien), tambahkan berikut ini ke wp-config.php:

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

Selanjutnya Anda membuat tugas untuk mengambil wp-cron.phphalaman satu menit sekali untuk memproses pekerjaan apa pun di bagian belakang, dari baris perintah masuk crontab -edan kemudian tambahkan baris yang terlihat seperti berikut:

*/1 * * * * /usr/bin/curl --silent http://example.com/wp-cron.php?doing_wp_cron=$(date +\%s.\%N) >/dev/null 
doublesharp
sumber
2
Jika Anda tidak memberikan nilai doing_wp_cron, ini sangat mungkin menyebabkan pekerjaan terkadang dieksekusi dua kali. Gunakan doing_wp_cron=$(date +\%s.\%N)untuk mencegah itu.
Alexander Garden
0

Periksa bahwa DISABLE_WP_CRON tidak disetel pada konfigurasi Anda.

Jika gagal, coba nonaktifkan semua plugin (kecuali kontrol inti - meskipun saya akan menggunakan wp-crontrol) dan lihat apakah pekerjaan inti Anda berfungsi. Jika ya, Anda mengalami gangguan plugin di suatu tempat.

Demikian pula, cobalah beralih ke tema standar dua puluh sesuatu.

Jika tidak ada yang membuat perbedaan, kemungkinan itu adalah masalah hosting.

vancoder
sumber
Saya tidak DISABLE_WP_CRONmengaturnya wp-config.php, saya akan mencoba lebih banyak hal dan kembali lagi nanti
Mike Madern
0

Periksa semua plugin yang menyembunyikan Wordpress.

Bagaimana cara melihat apakah ini masalahnya?

  1. Arahkan ke http: //yoursite.com/wp-cron.php Anda seharusnya melihat halaman kosong. Yang benar-benar kosong.
  2. Selain itu Anda harus melihat di cron job manager waktu di bawah "Eksekusi berikutnya": Pekerjaan Cron dijadwalkan - jika wp-cron.php berfungsi dengan baik (tidak hanya teks "Dalam antrian" - tetapi waktu tertentu - untuk beberapa entri "Dalam antrian" kadang-kadang OK, tetapi jika itu adalah satu-satunya hal Anda melihat -> cron Anda tidak berfungsi.)

+1. Jangan percaya plugin apa pun yang "memeriksa apakah cron berfungsi" - mis. Plugin pemeriksa status WP Cron telah menunjukkan bahwa cron berfungsi. Tapi ternyata tidak. Apa pun yang diperlihatkan - percayalah pada mata Anda dan bukan plugin ini!

Kesimpulan: Jika 404 kesalahan - matikan a) tidak hanya caching plugin seperti yang disarankan b) tetapi juga plugins yang menyembunyikan Wordpress.

Peter Cz
sumber