Как читать выражение cron
Cron — это синтаксис планирования в Linux и в подавляющем большинстве планировщиков задач. Он состоит из нескольких разделённых пробелами полей, каждое из которых описывает одно измерение времени. Ключ к чтению не в заучивании синтаксиса, а в понимании того, что поля соединяются союзом «и». Задача запускается, только когда совпадают все поля одновременно.
Что представляют собой пять полей
- Поле 1 — минута: 0–59
- Поле 2 — час: 0–23 по 24-часовому формату, то есть 15:00 записывается как 15
- Поле 3 — день месяца: 1–31
- Поле 4 — месяц: 1–12
- Поле 5 — день недели: 0–7, где и 0, и 7 означают воскресенье (в некоторых реализациях 1 — это понедельник, так что будьте внимательны)
Если планировщик поддерживает точность до секунд (Spring @Scheduled(cron=...), Quartz), добавляется поле секунд впереди, и получается шесть полей. Поэтому один и тот же шаблон в разных местах может «срабатывать чаще, чем ожидалось»: шаблон из пяти полей, разобранный как шесть, сдвигает каждое поле на одно.
Пять обозначений
- Конкретное значение:
30означает 30-ю минуту. - Диапазон:
9-18совпадает с 9 по 18 включительно с обеих сторон. - Список:
1,3,5означает любое из этих трёх значений. - Шаг:
*/5означает каждое 5-е значение начиная с начала;10-40/5означает каждые 5 минут с 10 до 40. - Подстановочный знак:
*означает «в этом поле подходит что угодно».
Их можно смешивать, поэтому 0,30 9-17 * * 1-5 означает «в начале часа и через полчаса, с 9 до 17 часов, с понедельника по пятницу».
Разбираем реальное выражение
Возьмём */5 9-18 * * 1-5 и пойдём по полям:
- Минута
*/5: каждые 5 минут (0, 5, 10 … 55) - Час
9-18: с 9 до 18 часов - День
*: любая дата - Месяц
*: любой месяц - День недели
1-5: с понедельника по пятницу
Вместе читается так: «каждые 5 минут с 9:00 до 18:55 по будням». Часто обновлять данные в рабочие часы и останавливаться после закрытия — очень распространённый шаблон.
Три ловушки, в которые попадают чаще всего
- Когда ограничены и «день месяца», и «день недели», действует «или», а не «и». Это самое контринтуитивное правило в cron.
0 0 13 * 5может задумываться как «13-е, если это пятница», но фактически означает «13-е число месяца или каждую пятницу» — более чем в десять раз чаще. Чтобы выразить «и», нужен другой подход или проверка внутри скрипта. - Не используйте
*/nдля точного периода через границу суток.*/7в поле минут — это на самом деле 0, 7, 14 … 56, а затем следующий час начинается с 0, то есть после 56-й минуты проходит всего 4 минуты. Для строгого периода (ровно каждые 7 минут) используйте поле секунд или специальный планировщик. - Поля года не существует. Стандартный cron не умеет выражать «только в 2026 году». Ограничьте год внутри скрипта задачи или используйте расширенный синтаксис, который это поддерживает (Quartz поддерживает; стандартный crontab — нет).
Чем это отличается от таймеров systemd
В современном Linux вместо crontab можно использовать таймеры systemd. Синтаксис другой: crontab — одна строка, тогда как systemd нужны и файл .service, и файл .timer. Преимущества systemd — более читаемый формат вроде OnCalendar, запись результата последнего запуска и политика догона пропущенных запусков (Persistent=true). Для машин, которые не работают круглосуточно, таймеры systemd надёжнее — cron просто не выполняет задачи, пропущенные пока машина была выключена.
Часовые пояса тоже важны: cron использует локальное время сервера. Контейнеры в большинстве случаев по умолчанию работают в UTC, поэтому ваше тщательно проверенное «ежедневно в 8 утра» в контейнере может стать 16 часами. Всегда проверяйте настройку часового пояса после развёртывания.
Как проверить выражение
Не в уме. Вставьте выражение в поле выше, и инструмент покажет следующие 10 запусков. Сверить времена — самая быстрая проверка из возможных, и она сразу вскрывает такие ловушки, как «или» дня и дня недели: если написать 0 0 13 * 5, в списке времён окажутся и каждое 13-е число, и каждая пятница, и проблема станет очевидна мгновенно.
Разбор происходит полностью в вашем браузере, доступ к сети не нужен.
Частые вопросы
Какое время у 0 6 * * *?
Ежедневно в 6 утра. Первое поле 0 означает нулевую минуту, второе поле 6 означает 6 часов, а оставшиеся три — подстановочные знаки без ограничений. Это один из самых распространённых шаблонов.
Поддерживаются ли макросы вида @daily?
Стандартный crontab поддерживает набор макросов: @daily (полночь каждого дня), @hourly, @weekly, @monthly, @yearly, @reboot (один раз после загрузки). Этот инструмент сосредоточен на стандартных числовых выражениях; подставьте макрос сами — @daily это 0 0 * * *.
Почему для дня недели работает 7?
Потому что и 0, и 7 определены как воскресенье, так что подходит любое. Но для понедельника используйте 1 — не пишите 8. В некоторых системах день недели определён как 1–7, где 1 — воскресенье, поэтому всегда уточняйте при переходе на другую платформу.
Предсказанные времена не совпадают с фактическим запуском?
Сначала проверьте часовой пояс. Контейнеры и облачные функции чаще всего по умолчанию в UTC, а это 8 часов разницы с пекинским временем. Затем уточните, ждёт ли планировщик пять полей или шесть — добавленное или пропущенное смещает всю строку.
Можно посчитать все запуски на следующий год?
Инструмент по умолчанию показывает 10, чего достаточно для проверки логики. Чтобы подсчитать итоги (например, оценить нагрузку задач), используйте собственные средства анализа планировщика или считайте на сервере.