Бэкап базы данных должен был запускаться каждую ночь в 2:00. Он не запускался последние 17 дней. Никто не заметил, потому что cron job не кричит, когда ломается — он просто тихо перестаёт работать. И вы узнаёте об этом в тот момент, когда нужно восстановиться из бэкапа, а последний валидный — трёхнедельной давности.
Это не гипотетический сценарий. Cron jobs — невидимые рабочие лошадки инфраструктуры: бэкапы, обработка очередей, отправка email, синхронизация данных, очистка логов. Когда они работают — о них не думают. Когда перестают — последствия бывают катастрофическими.
Почему cron jobs ломаются тихо
Обычный uptime-мониторинг не поможет. Он проверяет, отвечает ли сервер — а cron job не отвечает на запросы. Он запускается по расписанию, делает свою работу и завершается. Если не запустился — ничего не происходит. Буквально: нет процесса, нет ошибки, нет лога, нет алерта. Тишина.
Типичные причины, по которым cron jobs перестают работать:
Сервер перезагрузился — crontab загрузился, но пути к скриптам изменились, или environment variables не подтянулись.
Диск заполнился — cron daemon не может создать лог-файл и тихо игнорирует задачу.
Скрипт падает с ошибкой — Python-скрипт кидает exception, bash-скрипт встречает ошибку. Cron запустил задачу, но она завершилась с ненулевым кодом. По умолчанию cron отправляет email с ошибкой — но кто настраивает MTA на серверах в 2026?
Предыдущий запуск ещё не завершился — задача, которая должна запускаться каждые 5 минут, работает 7 минут. Без flock или аналогичного механизма запускается вторая копия, они мешают друг другу, обе падают.
Кто-то отредактировал crontab — при обновлении одной записи случайно удалили другую. Или деплой перезаписал crontab без важной задачи.
Heartbeat monitoring: принцип "dead man's switch"
Концепция проста и элегантна. Вместо того чтобы активно проверять cron job (что технически сложно — как проверить процесс, который работает 2 секунды раз в час?), вы переворачиваете модель: cron job сам сообщает, что он жив.
Как это работает:
1. Создаёте heartbeat monitor с ожидаемым интервалом (например, "каждые 60 минут").
2. Получаете уникальный URL для пинга (например, https://atomping.com/heartbeat/abc123).
3. Добавляете curl этого URL в конец своего cron-скрипта.
4. Если пинг приходит вовремя — всё хорошо. Если не приходит — heartbeat monitor открывает инцидент и отправляет алерт.
Это называется "dead man's switch" — по аналогии с механизмом в поездах: если машинист перестаёт нажимать кнопку каждые N секунд, поезд автоматически останавливается. Ваш cron job — "машинист". Heartbeat URL — "кнопка". Мониторинг — "автоматический тормоз".
Что мониторить: топ cron jobs, которые нельзя оставить без присмотра
Бэкапы
Абсолютный приоритет номер один. Бэкап, который не работает — хуже, чем отсутствие бэкапа, потому что вы думаете, что он есть. Мониторьте не только факт запуска, но и завершение: добавьте ping в самый конец скрипта, после проверки размера бэкап-файла. Если скрипт упал на середине — пинг не уйдёт.
Обработка очередей и email
Celery beat, sidekiq, bull — scheduled workers, которые обрабатывают фоновые задачи. Если они встали — письма не отправляются, заказы не обрабатываются, уведомления не доходят. Heartbeat на каждый worker process — минимальная страховка.
Синхронизация данных
ETL-пайплайны, синхронизация CRM с базой, импорт из внешних API. Если sync-задача перестала работать, данные расходятся — и вы узнаёте об этом, когда финансовый отчёт показывает неправильные цифры.
Очистка и ротация
Logrotate, очистка /tmp, удаление старых сессий, прунинг Docker images. Кажется неважным — до момента, когда диск заполняется на 100% и всё ложится. Heartbeat check на cleanup-задачу — 30 секунд настройки, которые предотвращают disk full incidents.
SSL-обновление
Certbot renewal — это тоже cron job. Если он перестал работать, через 30-60 дней SSL-сертификат истечёт. Двойная защита: heartbeat на certbot cron + SSL-мониторинг для отслеживания expiry date.
Как добавить heartbeat мониторинг к существующему cron job
Интеграция занимает буквально одну строку. Вот примеры для разных сценариев:
Простой bash-скрипт
#!/bin/bash
# Ваша задача
pg_dump mydb > /backups/db-$(date +%F).sql
# Пинг мониторинга — только если бэкап успешен
if [ $? -eq 0 ]; then curl -fsS --retry 3 https://atomping.com/heartbeat/YOUR-ID > /dev/null; fi
Python-скрипт
import requests
def main():
# ... ваша логика ...
process_data()
# Пинг после успешного завершения
requests.get("https://atomping.com/heartbeat/YOUR-ID", timeout=10)
В crontab напрямую
0 2 * * * /scripts/backup.sh && curl -fsS https://atomping.com/heartbeat/YOUR-ID > /dev/null
Ключевой момент: && гарантирует, что пинг отправится только если предыдущая команда завершилась успешно. Если backup.sh вернул ненулевой код — curl не выполнится, мониторинг не получит пинг и отправит алерт.
Grace period: учитываем реальность
Cron jobs не работают с точностью до секунды. Бэкап, который обычно занимает 30 секунд, может занять 5 минут при высокой нагрузке на диск. ETL-задача может растянуться из-за большого объёма данных. Если установить grace period слишком коротким — будете получать ложные алерты. Слишком длинный — поздно узнаете о проблеме.
Правило: grace period = 2x максимальное наблюдаемое время выполнения задачи. Если бэкап обычно занимает 1 минуту, но иногда растягивается до 3 — ставьте grace period 6 минут. Если задача запускается каждый час — grace period 10-15 минут обычно достаточно.
Паттерны мониторинга для разных архитектур
Один сервер, один crontab
Самый простой случай. Один heartbeat на каждую критичную задачу. Всё прозрачно: если пинг не пришёл — задача не отработала на этом сервере.
Несколько серверов, одна задача (HA cron)
Три сервера, но задачу должен выполнять только один (leader election через Redis lock, consul, или просто один назначенный сервер). Создайте один heartbeat — его пингует тот сервер, который реально выполнил задачу. Если лидер упал и failover не произошёл — пинг не придёт ни от кого.
Celery Beat / Sidekiq / Bull scheduler
Для task schedulers в фреймворках подход тот же: в конце задачи добавляете HTTP-вызов на heartbeat URL. В Celery это может быть отдельная задача, которая запускается после основной через chain или chord. В Sidekiq — callback after_perform.
Kubernetes CronJob
Kubernetes CronJob создаёт Pod по расписанию. Проблема: Pod может создаться, но не запуститься (ImagePullBackOff, resource limits). Или запуститься и упасть (OOMKilled). Heartbeat в конце container command — единственный надёжный способ узнать, что задача не просто запустилась, а завершилась успешно.
Распространённые ошибки при мониторинге cron jobs
Пинг в начале скрипта. Если пинг стоит перед основной логикой — мониторинг получит "всё хорошо" даже когда задача упадёт с ошибкой через секунду. Всегда ставьте пинг в самый конец, после всех проверок.
Безусловный пинг. backup.sh; curl heartbeat (с точкой с запятой) отправит пинг даже если backup.sh вернул ошибку. Используйте &&, чтобы пинг отправлялся только при успехе.
Нет retry для пинга. Сеть мигнула — curl не прошёл — мониторинг получил ложный алерт. Добавьте --retry 3 к curl-команде.
Мониторинг запуска, а не завершения. Знать, что cron daemon запустил задачу — полезно, но недостаточно. Задача могла зависнуть, упасть на середине, или работать вечно. Мониторьте именно успешное завершение.
С чего начать
Прямо сейчас откройте терминал и посмотрите crontab -l на ваших серверах. Выпишите все задачи. Отметьте критичные — те, чей сбой стоит денег, данных или доверия пользователей. Для каждой критичной задачи создайте heartbeat monitor в AtomPing и добавьте одну строку с curl в конец скрипта.
Вся настройка — 5 минут на задачу. А спокойствие, что ваши бэкапы, синхронизация и очистка реально работают — бесценно. Потому что худшее время узнать, что бэкап не работает — это момент, когда он нужен.
FAQ
What is cron job monitoring?
Cron job monitoring (also called heartbeat monitoring) tracks whether your scheduled tasks actually run on time. Instead of checking a URL, it works in reverse: your cron job sends a ping to a monitoring endpoint after completing. If the ping doesn't arrive within the expected window, the monitor alerts you that the job failed or is late.
How does heartbeat monitoring work?
You create a heartbeat monitor with an expected interval (e.g., every 5 minutes). The monitor generates a unique URL. You add a curl/wget call to that URL at the end of your cron job script. The monitoring service tracks when pings arrive. If no ping arrives within the expected interval plus a grace period, it triggers an alert.
What's the difference between cron monitoring and uptime monitoring?
Uptime monitoring is active — it sends requests to your servers. Cron monitoring is passive — it waits for your jobs to check in. Uptime monitoring answers 'is my server reachable?' while cron monitoring answers 'did my scheduled task actually run?' They complement each other and cover different failure modes.
Can I monitor cron jobs that run on multiple servers?
Yes. Create one heartbeat monitor per server, or use a single monitor for the job and have only one server ping it (the leader). For redundant cron setups where any server can run the job, use a single monitor — the first server that completes the job sends the ping.
What cron jobs should I monitor?
Any cron job whose failure impacts your business or data integrity. Priority targets: database backups, payment processing, email sending queues, report generation, cache warming, data sync between systems, SSL certificate renewal, log rotation, and cleanup tasks. If you'd only find out the job stopped days later — it needs monitoring.
How do I add monitoring to an existing cron job?
Add a single line at the end of your cron script: curl -fsS --retry 3 https://atomping.com/heartbeat/YOUR-ID > /dev/null. This sends a silent HTTP request to the monitoring endpoint after your job completes. If the job fails or hangs before reaching this line, no ping is sent, and the monitor alerts you.