Планировщик задач: запуск событий через Cron в CMS
Настройка выполнения событий через системный cron
Какое решение является наиболее надёжным для регулярного запуска отложенных обработчиков событий в 1С-Битрикс?
Наиболее эффективный способ - использование crontab на сервере совместно со специальным скриптом ядра. Этот подход гарантирует выполнение агентов и обработчиков событий в заданное время независимо от посещаемости сайта.
Пошаговая настройка:
- Определить путь к PHP CLI и корневой директории сайта.
- Добавить задачу в crontab:
* * * * * /usr/bin/php -f /var/www/site/bitrix/modules/main/tools/cron_events.php - Убедиться, что агенты в административной части включены для выполнения через cron (Настройки -> Производительность -> Агенты: "Запускать агенты при помощи cron").
- При необходимости создать собственный скрипт
/bitrix/php_interface/cron_events.phpс дополнительной инициализацией.
Пример модифицированного скрипта:
<?php
$_SERVER["DOCUMENT_ROOT"] = realpath(__DIR__."/..");
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
// дополнительная логика, например, логирование
CAgent::CheckAgents();
CCronEvent::CheckEvents();
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
?>
Bitrix cron events php (cron в 1с-битрикс для обработки событий)
В этом скрипте сначала подключается пролог, затем выполняются агенты и события, после чего эпилог.
Типичные проблемы:
- Php-скрипт не может быть выполнен из-за отсутствия прав на выполнение. Решение: проверить владельца файла и права (chmod 755).
- Агенты не запускаются, если не установлена опция "Запускать агенты при помощи cron" в настройках продукта.
- Таймауты при большом количестве агентов. Решение: использовать параметры
CAgent::CheckAgents(60);для ограничения времени выполнения. - Конфликты блокировок при параллельном выполнении. Решение: использовать файловые блокировки или flock в пользовательском скрипте.
Как выполнять обработку событий без доступа к серверному cron?
В условиях shared-хостинга без возможности crontab можно использовать внешние сервисы (например, cron-job.org, easycron). Они отправляют HTTP-запрос на специальную страницу сайта, которая эмулирует запуск агентов.
Для этого создаётся скрипт, доступный через веб, например /cron.php:
<?php
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
CAgent::CheckAgents();
CCronEvent::CheckEvents();
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
?>
Внешний сервис будет обращаться к этому URL каждую минуту. Недостаток: зависимость от внешнего сервиса и возможные таймауты при выполнении.
Как использовать только встроенные агенты без внешнего планировщика?
По умолчанию в 1С-Битрикс агенты могут выполняться при каждом посещении сайта. Это приводит к неконтролируемой нагрузке. Такой способ подходит только для очень низконагруженных проектов.
В настройках агентов нужно установить режим "Запускать агенты при каждом посещении". Но рекомендуется отключить этот режим и использовать cron, чтобы избежать случайных простоев.
Расширенные примеры настройки cron
Как настроить cron для нескольких сайтов в мультисайтовой конфигурации?
* * * * * /usr/bin/php -f /var/www/site1/bitrix/modules/main/tools/cron_events.php -- SITE_ID=s1
* * * * * /usr/bin/php -f /var/www/site2/bitrix/modules/main/tools/cron_events.php -- SITE_ID=s2
Внутри скрипта ядро учитывает переданный параметр SITE_ID.
Как ограничить время выполнения агентов?
// в cron_events.php
CAgent::CheckAgents(30); // максимум 30 секунд
CCronEvent::CheckEvents(30);
Агенты, которые не успели выполниться, перейдут на следующий вызов.
Как добавить логирование выполнения в файл?
// в cron_events.php
$_SERVER["DOCUMENT_ROOT"] = realpath(__DIR__."/..");
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");
$start = microtime(true);
CAgent::CheckAgents();
CCronEvent::CheckEvents();
$elapsed = microtime(true) - $start;
$log = date("Y-m-d H:i:s")." | Time: ".$elapsed."s | Memory: ".memory_get_peak_usage(true)."\n";
file_put_contents(__DIR__."/cron_log.txt", $log, FILE_APPEND);
require_once($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/epilog_after.php");
Результат в файле cron_log.txt:
2025-03-29 10:00:00 | Time: 0.123s | Memory: 2097152
Как обрабатывать события с пользовательскими параметрами?
// Добавление события с параметрами
\Bitrix\Main\EventManager::getInstance()->registerEventHandlerCompatible("main", "OnBeforeProlog", "cron_test", "CCronTest", "handleEvent", array("param1"=>"value1"));
// В файле cron_events.php просто вызывается CCronEvent::CheckEvents(), который автоматически обрабатывает все зарегистрированные события.
Событие будет выполнено при очередном вызове cron.
Как предотвратить одновременное выполнение скрипта cron?
$lockFile = __DIR__."/cron.lock";
$fp = fopen($lockFile, "w+");
if (flock($fp, LOCK_EX | LOCK_NB)) {
// выполнение агентов и событий
CAgent::CheckAgents();
CCronEvent::CheckEvents();
flock($fp, LOCK_UN);
} else {
echo "Скрипт уже выполняется. Выход.\n";
}
fclose($fp);
Если блокировка не получена, скрипт завершается без выполнения. Для надёжности стоит добавить проверку времени создания блокировки.