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 минут в моем почтовом ящике не было электронного письма.

Что я пробовал

С помощью плагина Core Control можно увидеть, какие задания cron запланированы.

Экран управления ядром

После нескольких изменений мне удалось получить их совершенно правильно, и, что лучше, когда я нажал «Запустить сейчас», я фактически получил электронное письмо в свой почтовый ящик.

Но почему cron не работает, когда я захожу на сайт через 8 минут. Что возможно не так с этим кодом? Я должен сказать, что я впервые использую WP Cron.

Я пробовал больше

После комментария vancoder id решил проверить, работает ли код, если я поместил следующий код прямо в 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( ), скажем, в верхней части включенного файла, загруженного шорткодом.
Майк Мадерн,
Работают ли какие-нибудь кроны? wp_version_check и т. д.?
ванкодер
Я не получил никаких крон для работы. В чем может быть проблема этого?
Майк Мадерн,
Чтобы подтвердить - даже основные задания cron терпят неудачу?
vancoder

Ответы:

8

Во-первых, не могли бы вы подтвердить, что у вас не включены плагины для кэширования? Кэширующие плагины могут мешать работе cron, потому что ваши посетители получают не живую страницу, а кешированную версию вашей страницы.

Если у вас включен плагин кэширования, вы можете выбрать одну из своих страниц, добавить исключение в настройки вашего плагина кеширования для этой страницы, чтобы он никогда не кэшировался.

Затем вам нужно будет вручную создать задание cron (используя cpanel, если вы находитесь в среде общего хостинга, или из терминала, если это VPS / выделенный сервер), которое будет посещать эту страницу каждые несколько минут.

Надеюсь, это поможет!

WPMU-DEV Ari
источник
У меня включен плагин кэширования! 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 минут (при условии, что у вас достаточно трафика на ваш сайт).


Примечания

Требуется посещение страницы для того, чтобы ваш хрон стрелял в правильное время.

Пример: если вы запланировали задание с 30-минутными интервалами, но никто не посещал ваш сайт в течение 4 часов, ваша задача cron не будет запущена, пока этот посетитель не придет на ваш сайт через 4 часа. Если вам действительно нужно, чтобы ваша задача выполнялась каждые 30 минут, то рекомендуется настроить законную работу cron через вашего веб-хостинг-провайдера, чтобы посещать ваш веб-сайт через определенные промежутки времени.

Работа в WordPress cron не делает ваш сайт медленным!

Возможно, вы думаете, что если выполнение cron-скрипта занимает много времени, посетителям придется ждать, пока скрипт не будет выполнен. Нет! Как это может быть возможно? Если вы посмотрите на 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
Этот ответ направит пользователя в правильном направлении для понимания и правильного планирования задач cron WordPress.
Майкл Эклунд
4
Это наверняка помогло мне понять графики cron с WordPress
Майк Мэдерн,
2
Майкл, ты должен отвечать чаще. Великий +1
кайзер
1
Я думаю, что WP_Cronиспользует GMT под капотом, как и остальные WP, так что было бы лучше запланировать первое событие time()вместо current_time().
Ян Данн
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 
doublesharp
источник
2
Если вы не дадите значению using_wp_cron, это может привести к тому, что задания иногда будут выполняться дважды. Используйте, doing_wp_cron=$(date +\%s.\%N)чтобы предотвратить это.
Александер Гарден
0

Убедитесь, что DISABLE_WP_CRON не установлен в вашей конфигурации.

В противном случае попробуйте отключить все плагины (кроме управления ядром - хотя я бы использовал wp-crontrol) и посмотреть, работают ли ваши основные задания. Если они это делают, вы где-то испытываете помехи от плагинов.

Точно так же попробуйте переключиться на стандартную тему двадцатых.

Если ничего из этого не имеет значения, скорее всего, это проблема хостинга.

vancoder
источник
Я не DISABLE_WP_CRONвставил в свой wp-config.php, я попробую больше вещей и вернусь позже
Майк Мэдерн
0

Проверьте любой плагин, который скрывает Wordpress.

Как узнать, в этом ли проблема?

  1. Перейдите на http (s): //yoursite.com/wp-cron.php. Вы должны увидеть пустую страницу. Совершенно пустой.
  2. Кроме того, вы должны видеть в менеджере заданий cron время в разделе «Следующее выполнение»: Задание Cron запланировано - если wp-cron.php работает правильно (не только текст «В очереди» - но заданное время - для некоторых записей «В очереди» иногда нормально, но если это единственное видишь -> твой cron не работает.)

+1. Не верьте никаким плагинам, которые "проверяют, работает ли cron" - например, плагин проверки статуса WP Cron показал, что cron работает. Но на самом деле это не так. Что бы это ни показывало - верь глазам своим, а не этому плагину!

Вывод: если это ошибка 404 - отключите а) не только плагины для кеширования, как предлагают другие б), но и любые плагины, которые скрывают Wordpress.

Питер Чз
источник