Що таке cron-вираз? Синтаксис, поля та 15 прикладів

Cron-вираз — це короткий рядок, який підказує планувальнику, коли запускати завдання. Стандартна форма має п’ять полів, розділених пробілами: хвилина, година, день місяця, місяць і день тижня. Наприклад, */15 * * * * означає «кожні 15 хвилин»: */15 у полі хвилин збігається з хвилинами 0, 15, 30 і 45, а чотири зірочки означають будь-яку годину, будь-який день, будь-який місяць і будь-який день тижня.

Спробуйте безкоштовно: Генератор Crontab Безкоштовно, без реєстрації.

Назва походить від cron — планувальника завдань в Unix, але сьогодні той самий синтаксис керує CI-конвеєрами, хмарними планувальниками та фреймворками застосунків, іноді з додатковими полями. У цьому посібнику пояснено синтаксис, 15 перевірених прикладів, поширені варіанти й помилки, через які завдання запускається не в той час. Щоб перевірити будь-який вираз під час читання, вставте його в безкоштовний генератор Crontab, який описує розклад простими словами.

П’ять полів cron-виразу

Поля читаються зліва направо:

ПозиціяПолеДопустимі значенняНазви
1Хвилина0–59–
2Година0–23–
3День місяця1–31–
4Місяць1–12jan–dec
5День тижня0–7 (і 0, і 7 — неділя)sun–sat

Години записують у 24-годинному форматі, тож 14:00 — це 14. Назви — це перші три літери англійської назви місяця чи дня, регістр не має значення. Деякі реалізації, зокрема cron у macOS, не приймають назви всередині діапазонів або списків, тому 1-5 переносніший, ніж mon-fri.

У файлі crontab команда йде після п’яти полів: 0 2 * * * /home/me/backup.sh. Загальносистемний /etc/crontab у Linux має ще й поле з іменем користувача перед командою.

Спеціальні символи: зірочка, кома, дефіс і скісна риска

Майже всю роботу виконують чотири символи:

СимволЗначенняПрикладЗбігається з
*Будь-яке значення* у полі годинГодини 0, 1, 2 … 23
,Список8,20 у полі годинГодини 8 і 20
-Діапазон (включно)1-5 у полі дня тижняЗ понеділка по п’ятницю
/Крок*/15 у полі хвилинХвилини 0, 15, 30, 45

Їх можна поєднувати. 9-17/2 у полі годин збігається з 9, 11, 13, 15 і 17, а 0-4,8-12 — це список із двох діапазонів.

Крок починається заново в кожному циклі. */7 у полі хвилин збігається з 0, 7, 14 … 56, а на початку наступної години знову з 0, тож між :56 і :00 минає чотири хвилини, а не сім. Крок, на який 60 хвилин або 24 години не діляться без остачі, ніколи не дає цілком рівномірного інтервалу.

15 прикладів cron-виразів

Кожен приклад перевірено поле за полем. Час указано в часовому поясі планувальника.

Cron-виразКоли запускається
* * * * *Щохвилини
*/5 * * * *Кожні 5 хвилин (:00, :05, :10 …)
30 * * * *Щогодини о 30-й хвилині (00:30, 01:30 …)
0 */2 * * *Кожні 2 години рівно (00:00, 02:00 … 22:00)
0 2 * * *Щодня о 02:00
0 8,20 * * *Двічі на день, о 08:00 і 20:00
0 9 * * 1-5З понеділка по п’ятницю о 09:00
*/15 9-17 * * 1-5Кожні 15 хвилин з 09:00 до 17:45, з понеділка по п’ятницю
0 6 * * 0,6У суботу й неділю о 06:00
0 0 * * 0Щонеділі опівночі
0 22 * * 5Щоп’ятниці о 22:00
0 0 1 * *1-го числа кожного місяця опівночі
0 12 15 * *15-го числа кожного місяця о 12:00
0 0 1 1,4,7,10 *Щокварталу: 1 січня, квітня, липня й жовтня опівночі
0 0 1 1 *Раз на рік, 1 січня опівночі

Дві деталі легко пропустити. По-перше, діапазони включають обидва кінці, тож 9-17 містить годину 17: */15 9-17 * * 1-5 запускається 36 разів на день, а останній запуск — о 17:45, а не о 17:00. По-друге, 0 0 1 */3 * дає такий самий щоквартальний розклад, бо */3 у полі місяця починається з 1 і збігається з місяцями 1, 4, 7 і 10.

Нестандартні макроси: @daily, @weekly і @reboot

Багато реалізацій cron приймають ключове слово замість п’яти полів:

МакросВідповідаєЗапускається
@yearly або @annually0 0 1 1 *Опівночі 1 січня
@monthly0 0 1 * *Опівночі 1-го числа кожного місяця
@weekly0 0 * * 0У неділю опівночі
@daily або @midnight0 0 * * *Щодня опівночі
@hourly0 * * * *На 0-й хвилині кожної години
@reboot–Один раз, коли запускається демон cron

Vixie cron, cronie та cron у macOS підтримують усі ці макроси, а CronJob у Kubernetes приймають ті, що прив’язані до часу, але не @reboot. Вони не входять до стандарту POSIX, тож перш ніж використовувати їх деінде, перевірте документацію.

Варіанти cron: секунди, роки й додаткові символи

Не кожен планувальник читає п’ять полів, тож перевірте, для якого діалекту ви пишете.

Пастка з днем місяця й днем тижня

У стандартному cron (Vixie) два поля дня поєднуються через АБО, а не через І, якщо обидва обмежені. Якщо одне з них — *, враховується лише інше. Тож 0 9 1-7 * 1 не означає «перший понеділок місяця». Завдання запускається о 09:00 у кожен із днів від 1 до 7 і додатково щопонеділка — разом 10 або 11 запусків на місяць.

Щоб запускати його лише в перший понеділок, залиште у виразі одне поле дня, а інше перевіряйте в команді:

0 9 1-7 * * [ "$(date +\%u)" = 1 ] && /path/to/report.sh

date +%u виводить день тижня числом від 1 до 7, де понеділок = 1. Знак відсотка треба екранувати як \%, бо cron перетворює неекранований % у команді на перенесення рядка. Quartz і AWS уникають цієї неоднозначності, вимагаючи ? в одному з двох полів дня.

Часові пояси й літній час

Cron працює в часовому поясі машини чи сервісу, що обчислює вираз, а на серверах і хмарних платформах це часто UTC, а не ваш місцевий час. 0 9 * * * на сервері з UTC запускається о 09:00 UTC, тобто о 05:00 у Нью-Йорку в період літнього часу (UTC−4). Конвертер часових поясів допоможе перевести місцевий час у пояс планувальника.

Літній час додає два особливі випадки в поясах, де його переводять: коли годинники переводять уперед, однієї місцевої години не існує, а коли назад — одна година трапляється двічі. Cron у Debian і cronie компенсують невеликі зміни годинника для завдань із фіксованим часом: запуск, що припадає на пропущену годину, відбувається невдовзі після переведення, а запуск у повторюваній годині не повторюється. Інші планувальники поводяться інакше, тож найнадійніше — тримати сервери в UTC або не ставити важливі завдання на години переведення годинників, зазвичай між 01:00 і 03:00 за місцевим часом.

Як перевірити cron-вираз

Помилковий cron-вираз рідко спричиняє повідомлення про помилку: завдання просто запускається не в той час або не запускається взагалі. Коротка процедура виявляє більшість проблем:

  1. Прочитайте вираз словами. Вставте його в інструмент, який описує розклад, і перевірте, чи речення відповідає задуму, особливо щодо двох полів дня.
  2. Перевірте команду з коротким розкладом. Тимчасово поставте * * * * *, щоб завдання запустилося протягом хвилини, а потім поверніть справжній розклад.
  3. Зберігайте вивід. Додайте >> /tmp/myjob.log 2>&1 після команди, щоб помилки записувалися у файл, а не губилися.
  4. Перегляньте журнал cron. Використовуйте grep CRON /var/log/syslog або journalctl -u cron у Debian та Ubuntu і journalctl -u crond у Fedora та RHEL.
  5. Використовуйте абсолютні шляхи. Cron запускає завдання з мінімальним оточенням і коротким PATH, тож команда, яка працює у вашому терміналі, може не спрацювати в cron.

Створіть вираз за допомогою генератора Crontab

Безкоштовний генератор Crontab працює повністю у вашому браузері. Введіть вираз або натисніть швидкий шаблон, як-от «Кожні 15 хв», «Щодня о 2:00» чи «Щопонеділка», і інструмент:

Перемикачі дають змогу отримати докладніший опис, 24-годинний формат і вибрати, чи номери днів тижня починаються з 0 для неділі. Символи, притаманні лише Quartz (L, W, #), і поле року не приймаються. Інструмент лише створює й перевіряє вираз; щоб запланувати завдання, скопіюйте його в crontab -e або в конфігурацію вашої платформи.

Поширені запитання

Чим cron відрізняється від crontab?

Cron — це фонова служба (демон), яка виконує заплановані завдання. Crontab, скорочення від «cron table», — це файл, у якому їх перелічено, по одному завданню в рядку: cron-вираз, а за ним команда. Власний crontab можна редагувати командою crontab -e, а переглянути — crontab -l.

Чи може cron-завдання запускатися кожні 30 секунд?

У стандартному cron — ні, бо його найменша одиниця — хвилина. Планувальники з полем секунд це вміють: Spring приймає */30 * * * * *, а Quartz потребує ? в одному з полів дня, як у */30 * * * * ?. У класичному cron поширений обхідний шлях — два рядки, що запускаються щохвилини, причому в одному з них перед командою стоїть sleep 30;.

Як запускати cron-завдання в останній день місяця?

У стандартному cron немає символу «останній день», але Quartz і AWS підтримують L у полі дня місяця. У класичному cron заплануйте дні з 28 по 31 і дайте команді перевірити, чи завтра 1-ше число:

0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/job.sh

date -d tomorrow — це синтаксис GNU date, який використовують у Linux. У macOS замість нього застосовуйте date -v+1d.

Спробуйте безкоштовно: Генератор Crontab Безкоштовно, без реєстрації.