Как запускать функцию каждые 5 минут?
У меня есть функция, которую нужно запускать каждые 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(){
// код размещается здесь
}
Вы можете создавать новые временные интервалы для расписания через 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 минут.

Если ваш сайт действительно испытывает высокую нагрузку, вы можете попробовать использовать функцию 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' );
}

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

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

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

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

Ответ @johano правильно объясняет, как настроить пользовательский интервал для WP cron задачи. Однако второй вопрос остался без ответа — как запускать крон каждую минуту:
В файл
wp-config.php
добавьте следующий код:define('DISABLE_WP_CRON', true);
Добавьте задание в 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) вы сможете достичь своей цели.

Вы можете активировать его при включении плагина вместо каждого вызова плагина:
//Добавляем вспомогательную функцию для более удобного ведения логов.
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("Плагин деактивирован.");
}

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

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

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

У меня есть возможное решение с использованием функции расписания и рекурсивной функции WP Ajax.
- Создайте запланированное событие на каждые 60 минут для запуска функции
- Эта функция будет запускать рекурсивную функцию с использованием Ajax через
file_get_contents()
- Ajax-функция будет иметь счетчик в базе данных с общим числом 60 (по одной записи на каждую минуту в часе).
- Эта ajax-функция будет проверять ваш счетчик для:
Если счетчик равен или больше 60, он сбрасывается и ожидает следующего запуска cron.
Если счетчик кратен 5 (то есть каждые 5 минут), будет выполняться ваша целевая функция
И, помимо условий, функция будет приостанавливаться на 59 секунд sleep(59);
(при условии, что ваша функция выполняется быстро). После паузы она снова запускает себя с помощью file_get_contents()
.
Важные моменты, на которые стоит обратить внимание:
- Создайте способ прерывания процесса (например, проверка значения в БД)
- Создайте способ предотвращения запуска 2 процессов одновременно
- В file_get_contents установите лимит времени в заголовке на 2-3 секунды, иначе сервер может держать множество процессов в ожидании без причины
- Можно использовать
set_time_limit(90);
, чтобы попытаться предотвратить прерывание функции сервером до завершения sleep
Это решение, не самое лучшее, и сервер может его заблокировать. Используя внешний cron, вы можете задать простую функцию, и сервер будет расходовать ресурсы на нее только раз в 5 минут. В этом же решении сервер будет использовать ресурсы постоянно.
