Переходите с UptimeRobot? Импортируйте мониторы одним кликом по ключу API только для чтения.Начать бесплатно →
  1. Главная
  2. Блог
  3. Инженерия

Мониторинг cron-задачи одной командой curl

Cron-задачи ломаются молча. Одна строка с curl — и вы получите оповещение, если бэкап, импорт или воркер не запустились, опоздали или завершились с ошибкой.

Инженерия

Ночная резервная копия не создаётся уже три недели. Никто не знал: cron-задача, которая падает, не создаёт ни страницы ошибки, ни красного статуса, ни жалоб клиентов. Она создаёт попытку восстановления на четвёртом месяце, которая ничего не находит.

Исправление настолько мало, что умещается в одну строку вашего crontab. В этом руководстве показан шаблон, варианты для платформ, которыми вы, вероятно, пользуетесь, и ошибки, из-за которых heartbeat-монитор лжёт.

Идея: пусть задача отмечается сама

Обычный монитор доступности спрашивает ваш сайт: «ты на месте?» Задаче по расписанию спрашивать нечего. Единственный сигнал — то, что она отработала. Поэтому направление меняется: когда задача завершается, она запрашивает URL. Если этот запрос не пришёл вовремя, монитор оповещает вас.

Как работает heartbeat-монитор Cron-задача запрашивает URL начала, выполняется, затем запрашивает URL успеха или URL сбоя. Монитор ждёт пинг успеха в пределах периода плюс периода допуска. Отсутствие пинга, опоздавший пинг и пинг сбоя вызывают оповещение. Cron-задача0 3 * * * backup.sh 1. /start (по желанию) 2. /h/ID при успехе или /h/ID/fail при сбое Heartbeat-мониторЖдёт пинг каждый период(или по расписанию cron) плюс период допуска. Что делает монитор Пинг вовремяСостояние: up.Оповещения нет. Пинг в периоде допускаСостояние: late.Монитор ждёт. Нет пинга или /failСостояние: down. Открытинцидент, ушло оповещение.
Тишина — это сигнал сбоя. Поэтому так ловятся задачи, которые вообще не запустились.

Шаг 1: создайте монитор

Создайте heartbeat-монитор. Вы получите URL вида https://ping.tenium.app/h/<id>. Идентификатор — это секрет, поэтому относитесь к URL как к паролю и не выкладывайте его в публичные репозитории. Heartbeat-мониторы доступны на тарифе Starter ($7 в месяц, heartbeat-мониторов: 20); в Pro их 100, в Agency — 500.

Выберите, как выражается расписание:

  • Период (каждые 15 минут) для воркеров и обработчиков очередей.
  • Выражение cron с часовым поясом (0 3 * * *, Europe/Tallinn) для задач, которые запускаются в фиксированное время. Если вы не уверены в выражении, конструктор cron-выражений прочитает его простым языком и покажет пять ближайших запусков.

Затем задайте период допуска: самое долгое обычное время выполнения плюс запас.

Шаг 2: добавьте строку в crontab

Самая короткая полезная версия:

0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 --retry 3 https://ping.tenium.app/h/abc123 > /dev/null

Важны три детали этой строки:

  • && означает, что curl запускается, только если скрипт завершился успешно. С ; вы сообщали бы об успехе упавшей задачи.
  • -m 10 --retry 3 не даёт медленной сети подвесить запись cron и повторяет неудавшийся пинг.
  • -fsS завершается ошибкой на ошибках HTTP, молчит при успехе и всё равно печатает ошибки, которые cron отправляет вам по почте.

Чтобы сообщать о сбоях сразу, а не ждать окончания периода допуска:

0 3 * * * /usr/local/bin/backup.sh && curl -fsS -m 10 https://ping.tenium.app/h/abc123 || curl -fsS -m 10 https://ping.tenium.app/h/abc123/fail

Шаг 3 (лучше): оберните задачу один раз

Когда задач десять, копировать эту строку неудобно. Небольшая обёртка держит всё в одном месте и отправляет код завершения и конец вывода, которые затем появляются в инциденте:

#!/bin/sh
# usage: ping-wrap ID command args...
ID="$1"; shift
BASE="https://ping.tenium.app/h/$ID"
curl -fsS -m 10 "$BASE/start" > /dev/null
OUT=$("$@" 2>&1); CODE=$?
if [ "$CODE" -eq 0 ]; then
  curl -fsS -m 10 --retry 3 "$BASE" > /dev/null
else
  printf '%s' "$OUT" | tail -c 4000 | curl -fsS -m 10 --data-binary @- "$BASE/fail?exit=$CODE" > /dev/null
fi
exit "$CODE"

Используйте так: 0 3 * * * /usr/local/bin/ping-wrap abc123 /usr/local/bin/backup.sh. Вызов /start включает учёт длительности: вы видите, сколько работает задача, а задача, которая началась, но не завершилась, отображается как опоздавшая.

Как выбрать период и допуск

Эти два числа определяют, как быстро вы узнаете о проблеме и как часто вас будят зря. Исходите из того, как задача ведёт себя на самом деле, а не из того, как она должна себя вести.

ЗадачаРасписаниеДопускПочему
Ночной бэкап базы данных0 3 * * *45 минутИдёт от 10 до 25 минут; в конце месяца медленнее
Heartbeat воркера очередикаждые 5 минут5 минутОдин пропущенный пинг означает зависший воркер, поэтому будьте строги
Почасовой импорт от поставщика15 * * * *20 минутAPI поставщика иногда отвечает медленно
Еженедельный отчёт по почте0 7 * * 12 часаЖдёт завершения других задач

Прежде чем назначить допуск, посмотрите последние десять запусков: возьмите самый медленный, прибавьте половину его длительности и округлите вверх. Пересматривайте значение, когда задача становится медленнее. Так вы не получаете ложных оповещений в обычные дни, а настоящий сбой всё равно заметите в тот же час, а не на следующий день.

Проверьте, прежде чем доверять

Монитор, который вы ни разу не видели сработавшим, — это догадка. Проверьте все три исхода один раз, в спокойный день:

  1. Запустите строку с curl вручную и убедитесь, что у монитора появилось свежее время последнего пинга.
  2. Запросите URL /fail вручную и убедитесь, что инцидент открылся, а оповещение дошло до контакта, который вы действительно читаете.
  3. Закомментируйте задачу в crontab, дождитесь, пока пройдут период и допуск, и убедитесь, что пришло оповещение «нет пинга». Затем верните задачу на место.

Запишите рядом с записью в crontab название монитора и владельца задачи. Через год никто не вспомнит, какой из двадцати heartbeat относится к какому скрипту. Если задачу передают другому человеку, проверьте, что контакт для оповещений тоже сменился: частая история — тревога уходит сотруднику, который давно работает в другой команде.

Варианты для разных платформ

Таймер systemd. Добавьте строку в юнит службы:

[Service]
Type=oneshot
ExecStart=/usr/local/bin/backup.sh
ExecStartPost=/usr/bin/curl -fsS -m 10 https://ping.tenium.app/h/abc123

При Type=oneshot ExecStartPost выполняется только после успешного завершения ExecStart, поэтому упавшая задача пинг не отправляет.

Docker. Отправляйте пинг из той же команды оболочки, что и задача, потому что у завершившегося контейнера нет «после»:

docker run --rm myimage sh -c 'run-job && wget -q -O- https://ping.tenium.app/h/abc123'

Kubernetes CronJob. Добавьте пинг последним шагом команды контейнера или запустите в поде второй контейнер, который дожидается первого. Храните идентификатор в Secret, а не в манифесте.

Планировщик заданий Windows. Как действие PowerShell: .\backup.ps1; if ($?) { Invoke-RestMethod https://ping.tenium.app/h/abc123 | Out-Null }.

WordPress. wp-cron срабатывает только тогда, когда кто-то заходит на сайт. В статье о пяти проверках для WordPress есть готовый must-use плагин, который отправляет пинг при каждом запуске по расписанию.

Ошибки, из-за которых heartbeat лжёт

  1. Пинг только в начале. Вы узнаёте, что задача началась, а не что она завершилась. Пингуйте в конце, а /start используйте как дополнение.
  2. ; вместо &&. Пинг уходит, хотя скрипт завершился ошибкой.
  3. Пинг не оттуда, где выполняется задача. Если задача на сервере A, а cron-пинг на сервере B, монитор ничего не говорит об A.
  4. Период допуска короче самого долгого запуска. Запуски в конце месяца самые медленные. Рассчитывайте допуск по ним.
  5. Смещение часового пояса. Выражение cron в мониторе должно использовать тот же пояс, что и сервер, включая переход на летнее время.
  6. Перекрывающиеся запуски. Задача, которая идёт дольше своего интервала, стартует дважды. Поставьте перед скриптом flock -n /tmp/backup.lock и пусть монитор сообщает, когда запуски пропускаются.
  7. Успех, который ничего не значит. Скрипт резервного копирования, который завершается с кодом 0 после записи пустого файла, — это зелёный свет для сломанной копии. Пусть скрипт проверяет размер результата или запускает тест восстановления и отправляет пинг, только если он пройден.

Что поставить перед этим

Для каждой важной задачи чек-лист короткий: heartbeat с разумным периодом допуска, контакт для оповещений, который вы читаете (почта на всех тарифах, Telegram на платных), и пометка о том, кто отвечает за задачу. Варианты описаны на странице мониторинга cron-задач, а сравнение Tenium и Cronitor пригодится, если мониторинг cron и очередей — ваше главное требование: Cronitor построен именно вокруг него, и на странице сказано, в чём он сильнее.

Создайте бесплатный аккаунт, чтобы попробовать остальные проверки; heartbeat-мониторы доступны со Starter.

Частые вопросы

Что такое heartbeat-мониторинг?

Вместо того чтобы проверять сервер снаружи, вы заставляете задачу самой отмечаться. Каждый раз, когда она завершается, она запрашивает уникальный URL. Если запрос не пришёл в ожидаемый период плюс период допуска, вы получаете оповещение. Это единственный способ заметить задачу, которая даже не запустилась.

Чем heartbeat отличается от проверки доступности?

Проверка доступности спрашивает публичный URL, отвечает ли он. У cron-задачи нет публичного URL, и когда она останавливается, снаружи ничего не падает. Heartbeat меняет направление: сбоем считается тишина.

Какой тариф нужен для мониторинга cron?

Heartbeat-мониторы доступны на тарифе Starter ($7 в месяц, heartbeat-мониторов: 20). В Pro их 100, в Agency — 500. На тарифе Free heartbeat-мониторов нет.

Каким должен быть период допуска?

Задайте самое долгое обычное время выполнения плюс запас. Ночной бэкап, который занимает 20 минут и запускается в 03:00, может использовать расписание cron 0 3 * * * и период допуска 45 минут. Слишком короткий период даёт ложные оповещения, слишком длинный задерживает настоящие.

Можно ли сообщать о сбое, а не только о тишине?

Да. Запросите тот же URL с добавлением /fail — монитор сразу перейдёт в состояние down и откроет инцидент. Можно добавить код завершения и последние строки вывода, и они появятся в инциденте.


Читайте также

Связанные страницы Tenium

Начните следить за первым сайтом бесплатно

30 мониторов бесплатно, проверки из 2 регионов, без банковской карты. Проверка SSL и срока действия домена — от $7 в месяц.