Перейти к содержанию

Агенты и фоновые задачи

Агенты и фоновые задачи помогают выполнять PHP-код автоматически.

  • Агенты — запускают код по расписанию.

  • Фоновые задачи — после отправки ответа пользователю.

Отличия агентов от фоновых задач

Характеристика Агенты Фоновые задачи
Запуск При посещении сайта посетителями (на хитах) и по расписанию через cron Сразу после ответа пользователю
Время выполнения Могут задерживаться Почти мгновенное
Приоритеты Нет Есть
Подходит для Регулярных задач Разовых тяжелых операций

Для сложных сценариев можно комбинировать оба подхода.

// Фоновая задача запускает агента для поэтапной обработки
$app->addBackgroundJob(function() {
    CAgent::AddAgent(
        "MyLongProcess::start();",
        "mymodule",
        "N",
        0
    );
});

Агенты

Агент — это запись в базе данных, которая содержит:

  • код для выполнения,

  • время следующего запуска,

  • интервал выполнения,

  • тип агента: периодический или непериодический.

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

Типы агентов

  • Периодические. Запускаются в указанное время.

Время следующего запуска = время предыдущего запуска + интервал.

  • Непериодические. Запускаются через заданный интервал и только после успешного завершения предыдущего выполнения, что исключает накладки.

Время следующего запуска = время окончания работы + интервал.

Зарегистрировать агента

Для работы с агентами используйте методы класса CAgent.

  • Метод addAgent добавляет агент.
CAgent::AddAgent(
    "MyFunction();",      // Имя функции для вызова
    "mymodule",           // Модуль. Пустое значение используют только в старом коде без модуля
    "N",                  // Периодичность: "N" — непериодический, "Y" — периодический
    3600,                 // Интервал в секундах. Например, 3600 сек, то есть 1 час
    "",                   // Дата проверки в формате YYYY-MM-DD HH:MI:SS
    "Y",                  // Активность: "Y" — активен, "N" — неактивен
    "",                   // Дата следующего выполнения в формате YYYY-MM-DD HH:MI:SS
    100,                  // Сортировка. Чем меньше значение, тем выше приоритет
    false,                // ID пользователя. По умолчанию false, то есть для системных агентов
    true                  // Выдавать ошибку при дублировании агента
);
  • Метод RemoveAgent удаляет агент.
CAgent::RemoveAgent(
    "MyFunction();",      // Имя функции агента
    "mymodule",           // Модуль. Пустое значение используют только в старом коде без модуля
    false                 // ID пользователя. По умолчанию false, то есть для системных агентов
);

Создать агента через интерфейс

Агента можно добавить через административный раздел на странице Настройки > Настройки продукта > Агенты. Нажмите Добавить агента и заполните параметры, аналогичные регистрации через функцию addAgent.

Запустить агента

  • На хитах. Агент срабатывает, когда посетитель заходит на страницу. Точность запуска зависит от посещаемости сайта. Система обрабатывает агентов по одному и при большом трафике агенты на хитах создают нагрузку на сайт.

  • Через cron. Агент запускается точно по расписанию и не зависит от посещаемости. Это снижает нагрузку на сайт.

Частично перевести запуск на cron

Агенты можно перевести на cron частично. Система продолжит запускать агенты при посещениях, а cron будет запускать только часть агентов.

  1. Откройте страницу Настройки > Инструменты > Командная PHP-строка. Выполните код:
// Включить частичный перевод агентов на cron
COption::SetOptionString(
    "main",                 // Модуль main
    "agents_use_crontab",   // Настройка использования cron
    "Y"                     // Y — разрешить, N — запретить
);

// Проверить текущее значение настройки
echo COption::GetOptionString("main", "agents_use_crontab", "N"); // вернет значение Y

После выполнения кода система будет запускать на хитах только периодические агенты.

  1. Добавьте задание cron на сервере:

bash prompt="$" # Выполнять каждые 10 минут от имени пользователя $ */10 * * * * bitrix /usr/bin/php -f /home/bitrix/www/bitrix/modules/main/tools/cron_events.php

Часть пути /home/bitrix/www/ замените на путь к вашему сайту.

Полностью перевести запуск на cron

Агенты не будут зависеть от посещаемости сайта и сработают точно по расписанию.

  1. Откройте страницу Настройки > Инструменты > Командная PHP-строка. Выполните код, который полностью отключит запуск агентов.
COption::SetOptionString(
    "main",                 // Модуль main
    "agents_use_crontab",   // Настройка использования cron
    "N"                     // Y — разрешить, N — запретить
);
echo COption::GetOptionString("main", "agents_use_crontab", "N"); // Выведет значение N — cron отключен для агентов

COption::SetOptionString(
    "main",                 // Модуль main
    "check_agents",         // Настройка проверки агентов
    "N"                     // Y — разрешить, N — запретить
);
echo COption::GetOptionString("main", "check_agents", "Y"); // Выведет значение N — значит автоматическая проверка агентов отключена
  1. Удалите в файле /bitrix/php_interface/dbconn.php константы BX_CRONTAB_SUPPORT и BX_CRONTAB.
define("BX_CRONTAB_SUPPORT", true);
define("BX_CRONTAB", true);
  1. Добавьте в файл строчку:
if (!(defined("CHK_EVENT") && CHK_EVENT===true))
{
    define("BX_CRONTAB_SUPPORT", true); // Разрешаем работу через cron
    // При этом обычные хиты не будут запускать агентов
}
  1. Создайте файл /bitrix/php_interface/cron_events.php, который будет проверять агенты и рассылки системных сообщений. Разместите в нем код:
<?php
// Устанавливаем корневую директорию
$_SERVER["DOCUMENT_ROOT"] = realpath(dirname(__FILE__)."/../..");

// Отключаем проверки для ускорения работы
define("NO_KEEP_STATISTIC", true);       // Не вести статистику
define("NOT_CHECK_PERMISSIONS", true);   // Не проверять права
define('BX_NO_ACCELERATOR_RESET', true); // Не сбрасывать акселератор

// Указываем, что это вызов через cron
define('CHK_EVENT', true);

// Разрешаем обработку после эпилога, для некоторых модулей
define('BX_WITH_ON_AFTER_EPILOG', true);

// Подключаем ядро Bitrix
require($_SERVER["DOCUMENT_ROOT"]."/bitrix/modules/main/include/prolog_before.php");

// Увеличиваем время выполнения
@set_time_limit(0);                     // Без ограничения времени
@ignore_user_abort(true);               // Продолжать при обрыве связи

// 1. Проверяем и запускаем агентов
CAgent::CheckAgents();

// Константы, которые обычно определяются в dbconn.php
define("BX_CRONTAB_SUPPORT", true);      // Поддержка cron
define("BX_CRONTAB", true);              // Пометка текущего выполнения как cron

// 2. Обрабатываем почтовые события (если модуль установлен)
if(CModule::IncludeModule('sender'))
{
    \Bitrix\Sender\MailingManager::checkPeriod(false);
    \Bitrix\Sender\MailingManager::checkSend();
}

// Завершаем работу
require($_SERVER['DOCUMENT_ROOT']."/bitrix/modules/main/tools/backup.php");
CMain::FinalActions();
  • Скрипт устанавливает CHK_EVENT=true перед подключением ядра.

  • Система определяет, что это cron, и разрешает работу агентов.

  • Функция CheckAgents() запускает всех агентов, которые должны выполниться.

  • Добавьте задание cron на сервере:

# Выполнять каждые 10 минут от имени пользователя
*/10 * * * * bitrix /usr/bin/php -f /home/bitrix/www/bitrix/php_interface/cron_events.php

Часть пути /home/bitrix/www/ замените на путь к вашему сайту.

Совет

Отключите задание cron со стандартным скриптом

/home/bitrix/www/bitrix/modules/main/tools/cron_events.php, чтобы избежать дублирования запусков.

Вернуть запуск агентов на хитах

  1. В таблице b_option удалите записи NAME = agents_use_crontab и NAME = check_agents.

  2. Очистите управляемый кеш в административном разделе.

  3. Удалите изменения из /bitrix/php_interface/dbconn.php.

Функции агентов

Функция агента — это PHP-код, который выполняется при запуске агента. Функция должна вернуть строку с кодом для следующего запуска. Чтобы остановить агента — пустую строку.

function TestAgent()
{
    mail('mail@gmail.com', 'Тест агента', 'Агент работает'); // код функции
    return "TestAgent();"; // Для повторного запуска
    // Для остановки агента передайте пустой return "";
}

Где размещать функции

  • В модуле. Укажите модуль при регистрации агента. Функция становится доступной после подключения модуля, то есть файла /bitrix/modules/[MODULE_ID]/include.php.
CAgent::AddAgent("Function();", "module_id");
  • Без модуля. Разместите функцию в файле /bitrix/php_interface/init.php. Модуль в параметрах регистрации указывать не нужно.
CAgent::AddAgent("Function();");

Для нового кода используйте собственный модуль. Файл init.php подключается на раннем этапе пролога, поэтому ошибка в файле может нарушить работу сайта.

Примеры агентов

  1. Очистить статистику.
CAgent::AddAgent(
    "CStatistic::CleanUpStatistics_2();", // имя функции
    "statistic",                          // идентификатор модуля
    "N",                                  // агент не критичен к кол-ву запусков
    86400,                                // интервал запуска — 1 сутки
    "07.04.2025 20:03:26",                // дата первой проверки на запуск
    "Y",                                  // агент активен
    "07.04.2025 20:03:26",                // дата первого запуска
    30
);
  1. Ограничить число запусков агента.
// Агент завершится после 5 запусков
class CMyModule
{
    public static function AgentLimited($count = 1)
    {
        if ($count >= 5) return ""; // Остановка агента
        return "CMyModule::AgentLimited(".($count+1).");"; // Следующий запуск
    }
}

// Регистрируем агент
CAgent::AddAgent(
    "CMyModule::AgentLimited();",
    "my_module",
    "Y",
    86400
);
  1. Обновить курс валют. Курс валюты не должен зависеть от хитов, поэтому агента нужно запускать через cron.
function AgentCurrencyUpdate()
{
    // Проверка подключения модуля валют
    if (!CModule::IncludeModule('currency'))
    {
        return "AgentCurrencyUpdate();"; // Повторить попытку
    }

    // Запрос к API ЦБ (возвращает курс рубля к валютам)
    $json = file_get_contents('https://api.exchangerate.host/latest?base=RUB');
    if (!$json)
    {
        return "AgentCurrencyUpdate();"; // Ошибка запроса — повторить
    }

    // Декодирование JSON и проверка данных
    $data = json_decode($json, true);
    $rates = $data['rates'] ?? [];
    if (empty($rates))
    {
        return "AgentCurrencyUpdate();"; // Нет данных — повторить
    }

    // Обновление курсов в базе
    foreach (['USD', 'EUR'] as $currency)
    {
        // Конвертируем курс (1 USD = X RUB, 1 RUB = 1/X USD)
        $convertedRate = 1 / ($rates[$currency] ?? 1);

        CCurrencyRates::Add([
            'CURRENCY' => $currency,    // Код валюты
            'DATE_RATE' => date('Y-m-d'), // Текущая дата
            'RATE' => $convertedRate,   // Рассчитанный курс
            'RATE_CNT' => 1             // Номинал, 1 единица валюты
        ]);
    }

    // Запланировать следующий запуск
    return "AgentCurrencyUpdate();";
}

Ограничения агентов

  1. Нет доступа к переменной $USER.

  2. Нельзя использовать авторизацию методом Authorize.

  3. Нет константы SITE_ID.

  4. Нельзя определить заранее язык на многоязычных сайтах.

Фоновые задачи

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

  1. Задача ставится в очередь.

  2. После отправки контента пользователю система выполняет задачу.

  3. Во время выполнения задачи ответ сервера не блокируется.

Фоновые задачи можно использовать:

  • чтобы отправить почту после регистрации,

  • сгенерировать документ в формате PDF,

  • выполнить синхронизацию с внешними API,

  • обработать загруженный файл,

  • массово обновить данные.

Добавить фоновую задачу

Метод addBackgroundJob добавляет фоновую задачу.

\Bitrix\Main\Application::addBackgroundJob(
    $job,
    $args,
    $priority
)
  • $job — вызываемая функция или метод. В качестве значения можно передать вызываемую функцию (callable) "myFunction" или массив для методов ["MyClass", "method"].

  • $args — массив аргументов для вызова функции или метода.

  • $priority — приоритет выполнения. Возможные значения:

\Bitrix\Main\Application::JOB_PRIORITY_NORMAL // 100, используется по умолчанию
\Bitrix\Main\Application::JOB_PRIORITY_LOW    // 50

Примеры фоновых задач

  1. Базовый пример с функцией отправки письма.
$app = \Bitrix\Main\Application::getInstance();
$app->addBackgroundJob(
    [EmailService::class, 'sendWelcome'],
    ['user@example.com', 'Добро пожаловать!'],
);

function sendWelcomeEmail($email, $message)
{
    mail($email, 'Уведомление', $message);
}
  1. Пример фоновой задачи с низким приоритетом. Функция обрабатывает загруженный файл.
// Подготовка файла перед фоновой задачей
$tmpFilePath = \Bitrix\Main\Application::getDocumentRoot().'/upload/tmp/'.uniqid('file_');

// Перемещаем загруженный файл в постоянное хранилище
if (!move_uploaded_file($_FILES['big_file']['tmp_name'], $tmpFilePath))
{
    throw new \Exception('File upload failed');
}

// Регистрируем фоновую задачу
$app = \Bitrix\Main\Application::getInstance();
$app->addBackgroundJob(
    // Используем callable-синтаксис для вызова функции, которая обработает файл
    [FileProcessor::class, 'processLargeFile'],
    // Передаем файл
    [
        'path' => $tmpFilePath,
        'original_name' => $_FILES['big_file']['name']
    ],
    // Устанавливаем низкий приоритет
    \Bitrix\Main\Application::JOB_PRIORITY_LOW
);