Как запускать функцию каждые 5 минут?

10 нояб. 2015 г., 10:47:43
Просмотры: 81.1K
Голосов: 25

У меня есть функция, которую нужно запускать каждые 5 минут. Я обратился к следующему примеру из документации:

<?php wp_schedule_event(time(), 'hourly', 'my_schedule_hook', $args); ?> 

Я хочу запускать эту функцию каждые 5 минут независимо от времени начала. Как я могу это сделать?

Также в документации говорится, что cron будет запускаться, когда посетитель заходит на сайт. Есть ли способ запускать cron точно по минутам, не дожидаясь посещения?

Допустим, следующую функцию нужно запускать каждые 5 минут, как это можно сделать с помощью wp_schedule_event() или wp_cron?

function run_evry_five_minutes(){
    // код размещается здесь
}
5
Комментарии

Вам лучше рассмотреть, например, Linux cron или сторонние сервисы cron, если вам нужен такой короткий интервал и точность.

birgire birgire
10 нояб. 2015 г. 10:58:45

Сайт имеет высокую нагрузку.. так что не нужно учитывать временной интервал.. он точно будет срабатывать каждые 2-3 минуты.. клиенты предпочитают делать это через functions.php

foolishcoder7721 foolishcoder7721
10 нояб. 2015 г. 11:01:48

Невозможно запустить php-файл без чего-то, что работает на сервере с таймером.

Andrew Welch Andrew Welch
10 нояб. 2015 г. 11:16:50

файл? мы говорим о функции в functions.php

foolishcoder7721 foolishcoder7721
10 нояб. 2015 г. 11:18:27

Как думаешь, бесплатный сервис мониторинга может быть тем пингом, который запускает CRON? http://newrelic.com/server-monitoring

jgraup jgraup
30 янв. 2016 г. 20:49:15
Все ответы на вопрос 7
0
52

Вы можете создавать новые временные интервалы для расписания через cron_schedules:

function my_cron_schedules($schedules){
    if(!isset($schedules["5min"])){
        $schedules["5min"] = array(
            'interval' => 5*60,
            'display' => __('Каждые 5 минут'));
    }
    if(!isset($schedules["30min"])){
        $schedules["30min"] = array(
            'interval' => 30*60,
            'display' => __('Каждые 30 минут'));
    }
    return $schedules;
}
add_filter('cron_schedules','my_cron_schedules');

Теперь вы можете запланировать выполнение вашей функции:

wp_schedule_event(time(), '5min', 'my_schedule_hook', $args);

Чтобы запланировать выполнение только один раз, оберните вызов в функцию и проверьте перед запуском:

$args = array(false);
function schedule_my_cron(){
    wp_schedule_event(time(), '5min', 'my_schedule_hook', $args);
}
if(!wp_next_scheduled('my_schedule_hook',$args)){
    add_action('init', 'schedule_my_cron');
}

Обратите внимание на параметр $args! Если не указать параметр $args в wp_next_scheduled, но указать его для wp_schedule_event, это приведет к почти бесконечному количеству одинаковых событий в расписании (вместо одного).

Наконец, создайте саму функцию, которую хотите выполнять:

function my_schedule_hook(){
    // ваш код здесь
}

Важно отметить, что wp-cron проверяет расписание и запускает запланированные задачи при каждой загрузке страницы.

Таким образом, если у вас сайт с низкой посещаемостью (например, 1 посетитель в час), wp-cron будет запускаться только при посещении сайта (раз в час). Если у вас высоконагруженный сайт с посетителями, которые загружают страницы каждую секунду, wp-cron будет запускаться каждую секунду, создавая дополнительную нагрузку на сервер.

Решение заключается в отключении wp-cron и его запуске через реальный cron-задачу с интервалом, соответствующим вашему самому частому расписанию (в вашем случае - 5 минут).

Lucas Rolff подробно объясняет проблему и предлагает решение.

В качестве альтернативы, если вы не хотите отключать wp-cron и настраивать реальный cron, вы можете использовать бесплатные сторонние сервисы, такие как UptimeRobot, которые будут обращаться к вашему сайту (и тем самым запускать wp-cron) каждые 5 минут.

30 янв. 2016 г. 01:23:34
7

Если ваш сайт действительно испытывает высокую нагрузку, вы можете попробовать использовать функцию set_transient() для выполнения кода (очень приблизительно) каждые 5 минут, например:

function run_every_five_minutes() {
    // Здесь, вероятно, стоит добавить логику, чтобы предотвратить повторный запуск сразу после выполнения.
    // ваш код здесь
}

if ( ! get_transient( 'every_5_minutes' ) ) {
    set_transient( 'every_5_minutes', true, 5 * MINUTE_IN_SECONDS );
    run_every_five_minutes();

    // Лучше использовать хук для вызова функции в плагине/теме
    //add_action( 'init', 'run_every_five_minutes' );
}
10 нояб. 2015 г. 12:24:05
Комментарии

Ну, эм, да?!...

bonger bonger
10 нояб. 2015 г. 13:10:06

Да... это НЕ работает.. Я использовал следующий код в functions.php, чтобы при посещении страницы обновлялась таблица в моей базе данных: function run_evry_five_minutes() { $homepage = file_get_contents('ссылка для посещения'); echo $homepage; }. Но таблица в БД не обновляется даже через 6 минут.

foolishcoder7721 foolishcoder7721
10 нояб. 2015 г. 13:43:49

Не знаю, почему у вас не работает, но если подумать, использование get_transient()/set_transient() без крон-задач имеет гораздо больше смысла, это проще, обновлю ответ...

bonger bonger
10 нояб. 2015 г. 14:03:40

@bonger это хорошая альтернатива для wp_schedule_event()?

Marko Kunic Marko Kunic
8 мая 2016 г. 22:16:10

@MarkoKunić Честно говоря, не знаю, не пробовал... это предлагалось как временное решение, но если попробуешь — дай нам знать! (Ответ Johano Fierra выглядит неплохо http://wordpress.stackexchange.com/a/216121/57034 )

bonger bonger
9 мая 2016 г. 14:55:31

@bonger это работает, но суть та же — если вы не на сайте, задача не выполнится

Marko Kunic Marko Kunic
10 мая 2016 г. 10:00:14

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

bonger bonger
11 мая 2016 г. 09:20:25
Показать остальные 2 комментариев
0

Ответ @johano правильно объясняет, как настроить пользовательский интервал для WP cron задачи. Однако второй вопрос остался без ответа — как запускать крон каждую минуту:

  1. В файл wp-config.php добавьте следующий код:

    define('DISABLE_WP_CRON', true);
    
  2. Добавьте задание в cron (crontab -e в unix/linux):

    1 * * * * wget -q -O - http://example.com/wp-cron.php?doing_wp_cron
    

Первая часть (шаг 1) отключит внутренний механизм cron в WordPress. Вторая часть (шаг 2) вручную запускает WordPress cron каждую минуту.

С ответом @Johano (как запускать задачу каждые 5 минут) и моим (как вручную запускать cron) вы сможете достичь своей цели.

5 сент. 2017 г. 07:05:52
0

Вы можете активировать его при включении плагина вместо каждого вызова плагина:

//Добавляем вспомогательную функцию для более удобного ведения логов.
if ( ! function_exists('write_log')) {
    function write_log ( $log )  {
        if ( is_array( $log ) || is_object( $log ) ) {
            error_log( print_r( $log, true ) );
        } else {
            error_log( $log );
        }
    }
}

/**
 * Не разрешаем прямой доступ к плагину
 **/
if ( ! defined( 'ABSPATH' ) ) {
    write_log( "Плагин не должен вызываться напрямую!" );
    exit; // Выход при прямом доступе
}

/**
 * -----------------------------------------------------------------------------------------------------------
 * Не забудьте настроить системный вызов страницы wp-cron как минимум каждые 30 минут.
 * Иначе нет гарантии, что триггер сработает.
 * -----------------------------------------------------------------------------------------------------------
 * Команда для Linux:
 * crontab -e
 * 30 * * * * wget http://<url>/wp-cron.php
 */

/**
 * Добавляем пользовательское расписание в WordPress.
 * @param $schedules array Существующие расписания
 *
 * @return mixed Существующие + новые расписания.
 */
function woocsp_schedules( $schedules ) {
    write_log("Создаем пользовательское расписание.");
    if ( ! isset( $schedules["10s"] ) ) {
        $schedules["10s"] = array(
            'interval' => 10,
            'display'  => __( 'Каждые 10 секунд' )
        );
    }

    write_log("Пользовательское расписание создано.");
    return $schedules;
}

//Добавляем фильтр расписаний cron с определенным выше расписанием.
add_filter( 'cron_schedules', 'woocsp_schedules' );

//Пользовательская функция, вызываемая по срабатыванию расписания.
function scheduleTriggered() {
    write_log( "Расписание сработало!" );
}
add_action( 'woocsp_cron_delivery', 'scheduleTriggered' );

// Регистрируем хук активации для выполнения операций только при активации плагина
register_activation_hook(__FILE__, 'woocsp_activation');
function woocsp_activation() {
    write_log("Активация плагина.");

    //Запускаем наш метод по пользовательскому событию расписания.
    if ( ! wp_get_schedule( 'woocsp_cron_delivery' ) ) {
        wp_schedule_event( time(), '10s', 'woocsp_cron_delivery' );
    }

    write_log("Плагин активирован.");
}

// Отключаем запланированные события при деактивации плагина.
register_deactivation_hook(__FILE__, 'woocsp_deactivation');
function woocsp_deactivation() {
    write_log("Деактивация плагина.");

    //Удаляем наш запланированный хук.
    wp_clear_scheduled_hook('woocsp_cron_delivery');

    write_log("Плагин деактивирован.");
}

5 мар. 2018 г. 13:05:42
1

К сожалению, помимо ожидания, пока кто-то посетит ваш сайт и запустит функцию, единственный другой вариант — это настроить задание cron на вашем сервере с помощью чего-то вроде этого https://stackoverflow.com/questions/878600/how-to-create-cronjob-using-bash. Или, если у вас есть интерфейс в стиле cPanel на сервере, иногда там есть графический интерфейс для настройки этого.

10 нояб. 2015 г. 10:55:05
Комментарии

да, я понимаю... У меня уже есть несколько крон-заданий, созданных через cPanel... но сейчас я пытаюсь запустить функцию из functions.php, потому что когда функция находится в плагине или в functions.php, мы не можем просить клиентов настраивать крон через cPanel самостоятельно...

foolishcoder7721 foolishcoder7721
10 нояб. 2015 г. 11:00:08
0

Плагин Cronjob Scheduler позволяет вам надежно и своевременно выполнять повторяющиеся задачи без необходимости посещения вашего сайта. Все, что вам нужно — это как минимум 1 действие и расписание Unix Crontab.

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

30 янв. 2016 г. 02:22:55
0

У меня есть возможное решение с использованием функции расписания и рекурсивной функции WP Ajax.

  1. Создайте запланированное событие на каждые 60 минут для запуска функции
  2. Эта функция будет запускать рекурсивную функцию с использованием Ajax через file_get_contents()
  3. Ajax-функция будет иметь счетчик в базе данных с общим числом 60 (по одной записи на каждую минуту в часе).
  4. Эта ajax-функция будет проверять ваш счетчик для:

Если счетчик равен или больше 60, он сбрасывается и ожидает следующего запуска cron.

Если счетчик кратен 5 (то есть каждые 5 минут), будет выполняться ваша целевая функция

И, помимо условий, функция будет приостанавливаться на 59 секунд sleep(59); (при условии, что ваша функция выполняется быстро). После паузы она снова запускает себя с помощью file_get_contents().

Важные моменты, на которые стоит обратить внимание:

  1. Создайте способ прерывания процесса (например, проверка значения в БД)
  2. Создайте способ предотвращения запуска 2 процессов одновременно
  3. В file_get_contents установите лимит времени в заголовке на 2-3 секунды, иначе сервер может держать множество процессов в ожидании без причины
  4. Можно использовать set_time_limit(90);, чтобы попытаться предотвратить прерывание функции сервером до завершения sleep

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

10 нояб. 2015 г. 14:46:52