WP Cron ไม่ทำงานเมื่อเวลาผ่านไป


16

เป้าหมาย

ฉันต้องการใช้wp_schedule_single_event( )เพื่อดำเนินการเหตุการณ์เดียวที่ส่งอีเมล 8 นาทีหลังจากผู้ใช้ส่งแบบฟอร์ม

ปัญหา

รหัสต่อไปนี้เป็นของฉัน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 ) );
}

และรหัสต่อไปนี้จะใช้ในการโทรschedule-event:

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

หลังจากรอนานกว่า 8 นาทีไม่มีอีเมลในกล่องจดหมายของฉัน

สิ่งที่ฉันพยายาม

ด้วยการควบคุมแกนของปลั๊กอินเป็นไปได้ที่จะเห็นงานที่กำหนดไว้

หน้าจอควบคุมหลัก

หลังจากการเปลี่ยนแปลงสองสามครั้งฉันจัดการเพื่อให้ถูกต้องและดีขึ้นเมื่อฉันกด "Run Now" ฉันได้รับอีเมลในกล่องจดหมายของฉัน

แต่ทำไม cron ไม่ทำงานเมื่อฉันเยี่ยมชมเว็บไซต์ของฉันหลังจาก 8 นาที มีอะไรผิดปกติกับรหัสนี้? ฉันต้องบอกว่านี่เป็นครั้งแรกที่ฉันใช้ WP Cron

ฉันพยายามมากขึ้น

หลังจากความคิดเห็นของรหัสvancoderตัดสินใจที่จะทดสอบว่ารหัสทำงานถ้าฉันใส่รหัสต่อไปนี้โดยตรงใน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'];
  }
}

ข้อเสียของรหัสนี้คือผู้ใช้จะต้องไปที่หน้าอื่นก่อนที่จะดำเนินการรหัสนี้ แต่ในทางกลับกันมันก็ไม่ได้ผลเช่นกันดังนั้นมันจะไม่ใช่ปัญหาแรกของฉัน ...


1
schedule_event( $_SESSION['insert_id'] );ยิงที่ไหนและอย่างไร
vancoder

ย่อมีไฟล์แยกต่างหาก (มีแบบฟอร์มใน) ในหน้าเมื่อแบบฟอร์มที่โพสต์โหลดหน้าใหม่ไฟล์เดียวกันจากนั้นดำเนินการschedule_event( )ให้พูดในด้านบนของไฟล์รวมโหลดโดยย่อ
Mike Madern

ทำใด ๆทำงาน crons? wp_version_check เป็นต้น
vancoder

ฉันไม่ได้รับcrons ใด ๆในการทำงาน อะไรคือปัญหาของสิ่งนั้น?
Mike Madern

เพื่อยืนยัน - แม้แต่งาน cron หลักที่ล้มเหลว?
vancoder

คำตอบ:


8

ก่อนอื่นคุณสามารถยืนยันได้ว่าคุณไม่ได้เปิดใช้งานปลั๊กอินแคช ปลั๊กอินสำหรับแคชอาจรบกวนงาน cron เนื่องจากผู้เข้าชมของคุณไม่ได้แสดงหน้าสด แต่เป็นหน้าเว็บในเวอร์ชันแคช

หากคุณเปิดใช้งานปลั๊กอินแคชคุณสามารถเลือกหนึ่งในหน้าเว็บของคุณเพิ่ม exclussion ให้กับการตั้งค่าของปลั๊กอินแคชสำหรับหน้านั้นเพื่อไม่ให้ถูกแคช

จากนั้นคุณจะต้องสร้างงาน cron ด้วยตนเอง (โดยใช้ cpanel หากคุณอยู่ในสภาพแวดล้อมการโฮสต์ที่ใช้ร่วมกันหรือจากเทอร์มินัลหากเป็น VPS / เซิร์ฟเวอร์เฉพาะ) ที่จะเข้าชมหน้านั้นทุกสองสามนาที

ฉันหวังว่าจะช่วย!


ฉันเปิดใช้งานปลั๊กอินแคชแล้ว! W3 Total Cache นั้นแม่นยำ
Mike Madern

14

ประการแรกกำหนดตารางเวลางาน 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;
}

คุณต้องตัดสินใจว่าจะกำหนดเวลาการแข่งขันได้ที่ไหนและเมื่อใด

นี่เป็นเพียงตัวอย่างโค้ดซึ่งทำให้การเรียกใช้เมธอดคลาสที่กำหนดเอง:

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

นี่คือรหัสที่กำหนดกิจกรรมจริง:

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

ตอนนี้สิ่งที่คุณต้องทำคือการโทรไปที่ชื่อของงาน cron ที่กำหนดเองของคุณ ในตัวอย่างนี้ชื่องาน cron custom_imap_importคือ

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

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

ดังนั้นในตัวอย่าง$this->do_imap_import();นี้เรียกว่าทุกๆ 30 นาที (สมมติว่าคุณมีปริมาณการเข้าชมเว็บไซต์เพียงพอ)


หมายเหตุ

ต้องมีการเยี่ยมชมหน้าเพื่อให้ cron ของคุณยิงในเวลาที่ถูกต้อง

ตัวอย่าง:หากคุณจัดตารางงานเป็นระยะเวลา 30 นาที แต่ไม่มีใครเข้าชมเว็บไซต์ของคุณเป็นเวลา 4 ชั่วโมงงาน cron ของคุณจะไม่ถูกไล่ออกจนกว่าผู้เยี่ยมชมจะมาที่ไซต์ของคุณ 4 ชั่วโมงในภายหลัง หากคุณต้องการใช้งานจริง ๆ ทุก 30 นาทีขอแนะนำให้ตั้งค่างาน cron ที่ถูกต้องผ่านผู้ให้บริการเว็บโฮสติ้งของคุณเพื่อเยี่ยมชมเว็บไซต์ของคุณในช่วงเวลาที่ต้องการ

WordPress cron jobs ไม่ทำให้เว็บไซต์ของคุณช้า!

บางทีคุณอาจคิดว่าถ้า cron-script ใช้เวลานานในการประมวลผลผู้เยี่ยมชมจะต้องรอจนกว่าสคริปต์จะทำงาน Nope! เป็นไปได้อย่างไร? หากคุณดูwp-cron.phpไฟล์คุณจะพบบรรทัด

ignore_user_abort(true);

มันเป็นการphp.iniกำหนดค่าที่กำหนดว่าถ้าคุณหยุดโหลดไซต์ / สคริปต์สคริปต์จะไม่หยุดการทำงาน

หากคุณดูwp-includes/cron.phpไฟล์คุณจะพบบรรทัดดังนี้

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

นั่นหมายความว่า WordPress จะรอเพียง 0.01 วินาทีสำหรับการกระตุ้นการทำงานจากนั้นมันจะยกเลิก แต่เมื่อคุณตั้งค่าignore_user_abortให้trueสคริปต์จะทำงาน ฟังก์ชั่นนี้เป็นข้อได้เปรียบอย่างมากในการใช้งานสคริปต์ขนาดใหญ่ในงาน WordPress cron

ฟังก์ชั่นที่ให้ความช่วยเหลือ:


6
นี่คือการตอบสนองที่ครอบคลุมอย่างน่าทึ่งซึ่งเท่าที่ฉันสามารถเห็นได้ล้มเหลวในการตอบคำถามจริง - ซึ่งเป็นสาเหตุที่งานที่จัดตารางเวลาทั้งหมด (รวมถึงงานหลัก) ล้มเหลว
vancoder

คำตอบนี้จะแนะนำผู้ใช้ในทิศทางที่ถูกต้องสำหรับการทำความเข้าใจและกำหนดเวลางาน WordPress cron อย่างถูกต้อง
Michael Ecklund

4
แน่นอนว่าช่วยให้ฉันเข้าใจตารางเวลา cron กับ WordPress
Mike Madern

2
Michael คุณควรตอบให้บ่อยขึ้น ยอดเยี่ยมหนึ่ง +1
kaiser

1
ผมคิดว่าWP_Cronการใช้งานในเขตเวลา GMT ภายใต้ประทุนเช่นส่วนที่เหลือของ WP จึงต้องการจะดีกว่าที่จะกำหนดเวลาเหตุการณ์ครั้งแรกที่แทนtime() current_time()
Ian Dunn

3

WordPress Cron ช่วยให้คุณสามารถกำหนดเวลางาน แต่พวกเขาจะดำเนินการเฉพาะเมื่อมีการร้องขอไปยังเว็บไซต์ สำหรับแต่ละคำขอที่ WordPress ได้รับจะตรวจสอบเพื่อดูว่ามีงาน cron ที่จะดำเนินการหรือไม่และหากไฟไหม้คำขอออกไป/wp-cron.php?doing_wp_cronแบบอะซิงโครนัสเพื่อประมวลผลงาน หากการเริ่มต้นตามกำหนดการของงานผ่านโดยไม่มีการร้องขอกระบวนการ cron จะไม่เริ่มขึ้น

เนื่องจากคุณสามารถดูและรันงานที่กำหนดเวลาไว้ของคุณได้อาจเป็นไปได้ว่าไม่มีคำขอที่เรียกให้งาน cron เริ่มโดยเฉพาะถ้าคุณใช้ปลั๊กอินแคช ตัวเลือกที่ดีที่สุดสำหรับการถ่ายนี้เวลาปกติมากขึ้นคือการปิดการใช้งานการตรวจสอบเริ่มต้นใน WordPress crontabและการใช้งาน

ก่อนปิดการใช้งานการตรวจสอบเริ่มต้น (ซึ่งสามารถช่วยเล็กน้อยกับประสิทธิภาพการทำงานด้านไคลเอ็นต์) เพิ่มต่อไปนี้เพื่อwp-config.php:

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

ถัดไปคุณสร้างงานเพื่อดึงwp-cron.phpหน้าหนึ่งครั้งเพื่อประมวลผลงานใด ๆ ที่ส่วนท้ายจากบรรทัดคำสั่งป้อนcrontab -eแล้วเพิ่มบรรทัดที่มีลักษณะดังต่อไปนี้:

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

2
หากคุณไม่ให้ค่า doing_wp_cron เป็นไปได้สูงว่าบางครั้งงานจะถูกดำเนินการสองครั้ง ใช้doing_wp_cron=$(date +\%s.\%N)เพื่อป้องกันสิ่งนั้น
Alexander Garden

0

ตรวจสอบว่าไม่ได้ตั้งค่า DISABLE_WP_CRON ในการกำหนดค่าของคุณ

ความล้มเหลวนั้นลองปิดการใช้งานปลั๊กอินทั้งหมด (ยกเว้นการควบคุมหลัก - แม้ว่าฉันจะใช้ wp-crontrol) และดูว่างานหลักของคุณทำงานหรือไม่ หากเป็นเช่นนั้นคุณกำลังประสบกับการรบกวนของปลั๊กอิน

ลองสลับไปใช้ชุดรูปแบบ twentysomething แบบมาตรฐาน

หากสิ่งเหล่านี้ไม่สร้างความแตกต่างโอกาสเป็นปัญหาโฮสติ้ง


ฉันไม่ได้DISABLE_WP_CRONตั้งค่าไว้wp-config.phpฉันจะลองทำหลายอย่างมากขึ้นและกลับมาใหม่ในภายหลัง
Mike Madern

0

ตรวจสอบปลั๊กอินที่ซ่อน Wordpress

จะดูว่าปัญหานี้เกิดขึ้นได้อย่างไร?

  1. ไปที่ http: //yoursite.com/wp-cron.php คุณควรเห็นหน้าว่าง อันที่ว่างเปล่าอย่างสมบูรณ์
  2. นอกจากนี้คุณต้องเห็นในตัวจัดการงาน cron เวลาภายใต้ "การดำเนินการครั้งต่อไป": กำหนดเวลางาน Cron - ถ้า wp-cron.php ทำงานอย่างถูกต้อง (ไม่เพียง แต่ข้อความ "ในคิว" - แต่เวลาที่กำหนด - สำหรับบางรายการ "ในคิว" บางครั้งก็โอเค แต่ถ้ามันเป็นสิ่งเดียว คุณเห็น -> cron ของคุณไม่ทำงาน)

+1 อย่าเชื่อปลั๊กอินใด ๆ ที่ "ตรวจสอบว่า cron ทำงาน" - เช่นปลั๊กอินตรวจสอบสถานะ WP Cron แสดงให้เห็นว่า cron ทำงาน แต่ในความเป็นจริงมันไม่ได้ สิ่งที่มันแสดง - เชื่อสายตาของคุณและไม่ใช่ปลั๊กอินนี้!

สรุป: หากเป็นข้อผิดพลาด 404 ให้ปิด a) ไม่เพียง แต่แคชปลั๊กอินตามที่คนอื่นแนะนำ b) แต่ยังมีปลั๊กอินที่ซ่อน Wordpress อยู่ด้วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.