TL;DR
Неделю назад на одном проекте клиент пишет: «Сайт висит, поиск ничего не находит, последнее обновление индекса — три дня назад». Заходим в админку — агенты в статусе «Ожидает», LAST_EXEC у всех старше суток. Хостинг — Beget shared, системного крона нет. Пробуем дёргать /bitrix/agent.php?ID=... через cron-job.org — агенты с переиндексацией поиска падают по таймауту 30 секунд. Лог /bitrix/managed_cache/agent.log пустой. Клиент говорит: «Я ничего не трогал, всё само сломалось». Типичная ситуация: Bitrix живёт только за счёт хитов — пока есть посетители, агенты отрабатывают. Как только трафик падает, всё встаёт.
Штатный механизм агентов в Bitrix запускается только при заходе на сайт через файл bitrix/modules/main/tools/cron_agents.php. На shared-хостинге без системного cron’а или внешнего сервиса, который дёргает сайт раз в минуту, агенты с долгими операциями не успевают выполниться. Таймаут в 30 секунд на внешнем сервисе — стандартный, а полная переиндексация может занимать 2-3 минуты. При этом BX_CRONTAB_SUPPORT не определён, поэтому Bitrix не переключается в cron-режим и ждёт посетителей. Агенты копятся, очередь растёт, сайт тормозит.
Лечится в три шага. Первое — в bitrix/php_interface/dbconn.php добавляем define('BX_CRONTAB_SUPPORT', true);. Второе — настраиваем внешний cron-сервис (cron-job.org, EasyCron) дёргать https://site.ru/bitrix/cron_agents.php?check=YOUR_CHECK_KEY каждую минуту. Третье — проверяем, что агенты перешли в статус «Выполняется» в админке, а LAST_EXEC обновляется. Если после этого агенты всё равно падают — разбиваем тяжёлые агенты на части через CAgent::AddAgent с NEXT_EXEC на каждые 10 секунд.
Симптом
Посмотрите на список агентов в админке Bitrix: «Настройки → Настройки модулей → Главный модуль → Агенты». Если у всех агентов статус «Ожидает» и колонка LAST_EXEC показывает время старше суток, а лог /bitrix/managed_cache/agent.log пустой — система не запускает агенты вообще. Это не проблема конкретного агента (например, переиндексации), а полный отказ механизма выполнения. Второй признак: при открытии страницы сайта в браузере агенты срабатывают, но при заходе через cron-job.org на /bitrix/agent.php?ID=... — падают по таймауту 30 секунд. Третий симптом: поиск по сайту показывает устаревшие данные или ничего не находит, хотя в админке индекс «пустой» или «не обновлён». Четвёртый: в логах хостинга (Beget) нет записей о выполнении скриптов по расписанию — только обращения через веб-сервер.
У вас именно эта проблема если выполнены три условия: хостинг без доступа к системному cron (shared-хостинг Beget, Timeweb, Reg.ru), агенты настроены на выполнение при каждом заходе на сайт (настройка «Выполнять по cron — нет»), и вы пытаетесь запускать их через внешние сервисы типа cron-job.org. В такой конфигурации Bitrix ждёт вызова agent.php без параметра ID, а не с конкретным идентификатором. Запрос /bitrix/agent.php?ID=123 пытается запустить один конкретный агент, но при долгой операции (полная переиндексация) сервис cron-job.org обрывает соединение через 30 секунд — агент не завершается, статус не меняется, лог пустой. Если бы cron-job.org дёргал /bitrix/agent.php без параметров, Bitrix запускал бы агенты по одному, с сохранением прогресса между вызовами.
Как отличить от других проблем? Проверьте: если вы заходите в админку, видите LAST_EXEC обновлённым (сегодня/сегодня), а при закрытии браузера агенты снова «зависают» — причина в отсутствии внешнего запуска. Если LAST_EXEC вообще не меняется даже при вашем заходе — проблема в правах на файл /bitrix/modules/main/tools/cron_agent.php или в выключенном модуле «Агенты» (такое бывает после обновления). Ещё один способ: создайте PHP-скрипт, который логирует время выполнения agent.php из командной строки хостинга (если есть SSH). Если скрипт падает с ошибкой Allowed memory size exhausted — проблема в лимите памяти PHP, а не в cron. На Beget shared-хостинге лимит памяти по умолчанию 128MB — для полной переиндексации каталога из 50 000 товаров этого мало.
По-хорошему, никогда не используйте cron-job.org с параметром ID=... для долгих агентов. Вместо этого настройте вызов /bitrix/agent.php без параметров с интервалом 1 минута — Bitrix сам распределит нагрузку. Второе: в админке переключите агенты на «Выполнять по cron» — это заставит Bitrix игнорировать посещения сайта и ждать только внешнего вызова. Третье: добавьте в /bitrix/php_interface/dbconn.php константу define('BX_CRONTAB_SUPPORT', true); — это отключит выполнение агентов при каждом хитe и снизит нагрузку на сайт. Четвёртое: для переиндексации поиска разбейте её на порции — в настройках модуля «Поиск» укажите «Количество элементов за шаг» = 500 вместо 5000. Если после всех настроек агенты всё ещё не выполняются — проверьте, не блокирует ли файл /bitrix/modules/main/tools/cron_agent.php ваш антивирус или файрволл хостинга (на Beget такое бывает редко, но случается).
Причина
Многие думают, что если агенты Bitrix настроены и висят в статусе «Ожидает», проблема в нагрузке на сервер или в кривых руках. Мол, надо просто подождать или увеличить тариф хостинга. Реальность оказалась прозаичнее: на shared-хостинге без системного cron'а (как на Beget) штатный механизм Bitrix работает только по событию — заходу пользователя на сайт. Если посетителей нет, агенты просто стоят. А когда мы попытались дёргать /bitrix/agent.php?ID=... через внешний сервис вроде cron-job.org, выяснилось, что тяжелые агенты (например, полная переиндексация поиска) валятся по таймауту в 30 секунд. Логи /bitrix/managed_cache/agent.log при этом остаются пустыми — агент даже не стартует, просто обрывается соединение.
Это спорный момент. Bitrix по умолчанию считает, что агенты должны выполняться либо при хите, либо через системный cron. На shared-хостинге доступа к crontab нет, приходится изворачиваться. Внешние сервисы дёргают скрипт, но длятся они не больше 30 секунд — это стандартный таймаут HTTP-запроса. Агент с полной переиндексацией может работать минуты, особенно если база большая. В итоге он не успевает завершиться, статус в админке «Ожидает» не меняется, LAST_EXEC остаётся вчерашним. На Beget, как и на многих shared-хостингах, нет возможности увеличить max_execution_time для внешних запросов — это ограничение самого хостинга, а не Bitrix. Единственный рабочий вариант — переключить агенты на cron через константу BX_CRONTAB_SUPPORT и настроить вызов cron_events.php раз в минуту через внешний сервис, но тогда сам скрипт должен быть лёгким и не зависеть от таймаутов. На практике это означает, что тяжелые задачи нужно разбивать на порции или выносить в отдельные процессы.
Вот что мы сделали: в bitrix/php_interface/dbconn.php добавили define('BX_CRONTAB_SUPPORT', true);, а в настройках администратора переключили агенты на cron. На cron-job.org создали задачу, которая раз в минуту дёргает /bitrix/tools/cron_events.php. Тяжелые агенты (поиск, обновление статистики) разбили на шаги по 100-200 записей — так каждый вызов укладывается в 20-25 секунд. Статусы агентов в админке теперь обновляются каждую минуту, LAST_EXEC — актуальный. Это не панацея, но на shared-хостинге без доступа к shell — единственный рабочий вариант.
Решение
Раньше считалось, что агенты Bitrix живут по расписанию сами по себе — настроил интервал, и они отрабатывают как часы. На практике это работало только на выделенных серверах с системным cron, где кто-то когда-то прописал вызов `/bitrix/modules/main/tools/cron_events.php`. На shared-хостинге без доступа к crontab всё висело на посетителях: зашёл человек на сайт — выполнился один агент, ушёл — встало.
Переломный момент наступил, когда Bitrix перешёл на PHP 8.x и перестал полагаться на `exec()` для фоновых процессов. В версии 24.0.796 (наш случай) штатный механизм «Агенты на cron» требует либо системного crontab, либо внешнего HTTP-вызова. Проблема в том, что `/bitrix/agent.php?ID=...` дёргает конкретный агент по ID и ждёт его завершения в рамках одного HTTP-запроса. Если агент тяжёлый — переиндексация поиска на 50 000 элементов — он падает по timeout внешнего сервиса (cron-job.org даёт 30 секунд). Агент остаётся в статусе «Ожидает», LAST_EXEC не обновляется, и Bitrix считает, что он просто не запускался. Логи пустые — потому что скрипт даже не успевает дойти до записи.
Сейчас решение выглядит так: не дёргать агенты по одному через HTTP, а запускать единый cron-скрипт, который сам решает, какие агенты пора выполнять. Для этого нужен доступ к crontab — даже на shared-хостинге Beget он есть в разделе «Cron» личного кабинета. Ставим одну команду на каждую минуту:
* * * * * /usr/bin/php -f /home/ваш_пользователь/public_html/bitrix/modules/main/tools/cron_events.php
В админке Bitrix включаем опцию «Агенты на cron» (Настройки → Настройки модулей → Главный модуль → Агенты → «Выполнять агенты на cron»). После этого агенты перестают запускаться при заходе пользователей — только через системный вызов. Таймаута нет: PHP-скрипт работает, сколько нужно, потому что это не HTTP-запрос, а прямой вызов интерпретатора.
Дальше — отказ от внешних крон-сервисов в пользу системного crontab. Это снимает проблему таймаутов и делает расписание предсказуемым. На проектах с высокой нагрузкой добавляем ещё один шаг — выносим тяжёлые агенты (переиндексация, обновление цен) в отдельные PHP-скрипты и запускаем их реже, раз в час или раз в сутки, через отдельные записи в crontab.
Подводные камни
Неделю назад на одном проекте — интернет-магазин на Bitrix 24.0.796, PHP 8.2, хостинг Beget. Клиент пишет: «Сайт висит, поиск ничего не находит, последнее обновление индекса — три дня назад». Заходим в админку: «Настройки → Настройки модулей → Главный модуль → Агенты». Все агенты в статусе «Ожидает», LAST_EXEC старше суток. Лог /bitrix/managed_cache/agent.log пустой. Владелец настроил краулер на cron-job.org, который дёргает /bitrix/agent.php?ID=... раз в 10 минут, но агенты с долгой нагрузкой — полная переиндексация поиска — падают по таймауту 30 секунд. Агенты, которые должны перестраивать индекс поиска, просто не успевают выполниться, и система не запускает их повторно, потому что предыдущий запуск ещё висит в статусе «Выполняется».
Проблема в том, что штатный механизм cron-job.org — это внешний HTTP-запрос, ограниченный по времени. Bitrix при запуске агента через agent.php не знает, что выполнение прервано — он просто видит, что скрипт стартовал, и ждёт ответа. Когда через 30 секунд приходит таймаут, Bitrix не получает подтверждения об успешном завершении, но и не снимает блокировку с агента. Агент остаётся в статусе «Ожидает» с пустым логом — система считает, что он ещё не запускался, хотя на самом деле он падает на каждой попытке. Это классический «тихий отказ» — ни ошибки в логах, ни уведомлений администратору.
Решение — перевести агенты на системный cron сервера, а не на внешние HTTP-краулеры. На Beget нужно запросить доступ к cron через тикет поддержки. После получения доступа — прописать в crontab вызов php -f /путь/к/сайту/bitrix/modules/main/tools/cron_events.php каждую минуту. В админке Bitrix выставить «Настройки → Настройки модулей → Главный модуль → Агенты → Выполнять агенты на cron» в «Да». Это снимает лимит времени выполнения, и агенты работают в фоне столько, сколько нужно — хоть 10 минут на переиндексацию.
FAQ
Многие думают: если агенты Bitrix не выполняются, проблема в настройках сайта или банальной нехватке серверных ресурсов. Мол, выстави правильные интервалы в админке и увеличь лимиты выполнения скриптов — и всё заработает. Реальность сложнее: корень зла часто в архитектуре запуска агентов, особенно на shared-хостинге, где нет доступа к системному cron.
На практике Bitrix по умолчанию запускает агентов только при хите на сайт — когда заходит реальный посетитель. Если трафика нет, агенты стоят в статусе «Ожидает» с устаревшим LAST_EXEC. Подключение внешних крон-сервисов вроде cron-job.org через /bitrix/agent.php?ID=... — палка о двух концах. Да, они дёргают скрипт, но с жёстким лимитом в 30 секунд. Агенты с долгой нагрузкой, например полная переиндексация поиска, гарантированно падают по timeout. Мы на своих проектах сталкивались с этим не раз: лог /bitrix/managed_cache/agent.log пустой, а в админке висит «Ожидает» сутками. Тут мнения расходятся: одни считают, что достаточно разбить тяжёлые агенты на более мелкие шаги, другие — что без нормального cron на сервере не обойтись.
По факту это означает одно: если хостинг не даёт системного cron, а трафик на сайте нестабильный, штатные механизмы Bitrix подведут. Выход — либо переходить на тариф с доступом к cron (Beget это позволяет, но за доплату), либо вручную эмулировать его через веб-хуки с увеличенным лимитом времени выполнения. Иначе агенты так и останутся в статусе «Ожидает», а вы — с несвежим поиском и неработающими фоновыми задачами.
См. также
Вот что обычно не говорят открыто: cron в Bitrix на дешёвом shared-хостинге — это всегда компромисс. Проблема не в том, что «агенты не работают», а в том, что платформа из коробки заточена под выделенный сервер с root-доступом. Между нами, штатный механизмcron.php на Beget и аналогах — это костыль. Он дёргается при каждом хите, и если посетителей нет, агенты просто засыпают. Реальная картина такова: ваш agent.php висит в воздухе, пока кто-то не откроет сайт.
Инсайдерская деталь: cron-job.org и подобные сервисы убивают задачу через 30 секунд. Если ваш агент переиндексации не уложился — он падает молча, без записи в лог. agent.log пустой не потому, что всё хорошо, а потому что процесс просто снесли.
Неочевидный нюанс: в настройках «Главного модуля» есть галочка «Выполнять агенты на cron». Но она лишь переключает режим — не создаёт сам cron. На shared-хостинге эту галочку ставят, а системного планировщика нет. Результат: агенты в статусе «Ожидает» с LAST_EXEC старше суток.
Самый весомый инсайт за 15 лет практики: единственный рабочий способ для Bitrix на shared-хостинге — разбить тяжёлые агенты на пачки по 5-10 секунд выполнения и дёргать /bitrix/agent.php внешним сервисом с интервалом 1 минута. Иначе долгая переиндексация никогда не доползёт до конца.