Що таке 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–12 jandec
5 День тижня 0–7 (і 0, і 7 — неділя) sunsat

Години записують у 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 або @annually 0 0 1 1 * Опівночі 1 січня
@monthly 0 0 1 * * Опівночі 1-го числа кожного місяця
@weekly 0 0 * * 0 У неділю опівночі
@daily або @midnight 0 0 * * * Щодня опівночі
@hourly 0 * * * * На 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 Безкоштовно, без реєстрації.