Самое дорогое выражение cron, которое я когда-либо писал, было 0 0 * * 0. Он еженедельно публиковал электронное письмо-дайджест для Laravel SaaS, который я создавал, и я был абсолютно уверен, что это означает "полночь в последний день недели." Это означает полночь воскресенья. Моя ментальная модель сказала, что неделя закончилась в субботу. В течение пяти недель клиенты получали свой "неделя в обзоре и квоте; электронная почта на день позже, и никто в команде не поймал ее, потому что никто в команде тоже не умел читать cron - мы все просто щурились на пять полей и кивали.
В этом грязный секрет синтаксиса Cron: почти каждый, кто его пишет, соответствует шаблону, который они наполовину помнят. Формат сорок с лишним лет, достаточно плотный, чтобы один символ полностью менял расписание, и он терпит неудачу. Нет ошибки компилятора для "запуска в неподходящий день". Работа просто работает не в тот день, навсегда, пока кто-нибудь не заметит.
равняется синтаксический анализатор выражение cron закрывает этот пробел. Вы вставляете выражение, и оно сообщает вам простым английским языком, что на самом деле произойдет - 0 0 * * 0 возвращается как & quot;В 00:00, в воскресенье" - плюс когда начнутся следующие запуски. Этот шаг возврата - это разница между отправкой расписания и отправкой предположения. Я построил тот, что был на Toolz.dev, потому что мне надоело переключение контекста на терминал, и потому что беспорядок wp-cron, с которым я имел дело в течение многих лет в WP Adminify, научил меня, что ошибки планирования - это самые терпеливые ошибки в программном обеспечении.
В этом руководстве рассказывается о том, как использовать синтаксический анализатор, как на самом деле работают пять полей (включая два причуды, вызывающие большинство производственных инцидентов) и где синтаксис cron различается кронтаб, Действия GitHub, Кварц и Ларавель.
TL;DR: Вставьте любое выражение crontab в Toolz.dev парсер Cron и получите простой английский перевод плюс предстоящее время выполнения - мгновенно, на стороне клиента, без регистрации. Прежде чем развернуть расписание, всегда проверяйте две вещи: нумерацию дня недели (0 и 7 - воскресенье) и часовой пояс, в котором работает планировщик (GitHub Actions - всегда UTC). Соедините его с Конвертер времени отметки времени Когда вам нужно перевести эти следующие временные прогоны между зонами, а также Калькулятор разницы дат к интервалам проверки здравомыслия.
Основные характеристики
обычный перевод
Основная работа парсера — это поворот */15 9-17 * * 1-5 в "Каждую 15-ю минуту мимо часа 9, 10, 11, 12, 13, 14, 15, 16 и 17, в понедельник, вторник, среду, четверг и пятницу." It's многословно - перечисляет, а не сворачивает "9 через 17" обратно в диапазон - и в этом многословие суть. Перечисление однозначно; обобщенный диапазон - это еще один шанс неправильно прочитать. Предложение - это то, что вы можете вставить в описание запроса на вытягивание, прочитать вслух в стойке или показать нетехнический заинтересованный участник. Необработанное выражение не имеет значения. По моему опыту, перевод имеет наибольшее значение во время проверки кода: рецензент, который будет штамповать пять загадочных полей, немедленно поймает " подождите, почему 17-й час, когда работа должна прекратиться в 17 часов?" когда каждый час будет вычеркнут. Перевод делает расписание фальсифицируемым, что именно является необработанным синтаксисом.
Следующий запуск
Зная, что такое выражение средство половина проблемы; знать, когда она стреляет рядом это другая половина. синтаксический анализатор вычисляет следующие пять раз выполнения, чтобы вы могли взглянуть на них против своего намерения. Здесь всплывают тонкие ошибки - выражение, которое хорошо читается на английском языке, но дает следующий запуск "в 27 дней " потому что вы перепутали день месяца с месяцем или тот, который срабатывает в 03:00 сегодня вечером, когда вы имели в виду 03:00 после выходных. Я проверяю список следующего запуска каждый раз сейчас, даже для выражений I' уверен в. Особенно для выражений I' уверен в этом - см. вступительный анекдот.
Две детали того, как вычисляются те времена. Во-первых, они оцениваются в Локальный часовой пояс вашего браузера, не UTC и не ваш сервер & #39;s зона - каждый запуск отображается дважды, один раз как локальная метка времени и один раз как эквивалентный момент UTC, так что вы можете прочитать, что соответствует вашей цели развертывания. во-вторых, когда и день месяца, и день недели ограничены, парсер применяет реальную семантику cron's ИЛИ, а не И: 0 0 1 * 1 Пожар 1 числа месяца а Каждый понедельник не только по понедельникам, которые приходится на 1-го. Это правило сбивает с толку опытных людей, и, видя пять конкретных дат, это делает очевидным так, как это предложение никогда не делает.
Один грубый край: невозможный выражение, как 0 0 30 2 * (30 февраля) анализирует как действительный, с радостью описывает себя как & quot;В 00:00, в день месяца 30, в феврале, & quot; а затем показывает пустой список следующих прогонов. Пусто - значит никогда. Это и #39;s правильно, но это и #39;s тихо - & quot;это расписание никогда не сработает иquot; предупреждение - это очевидное улучшение, и я еще и #39;t еще не построил его.
разбивка
Анализатор разбивает выражение на пять компонентов - минуту, час, день месяца, месяц, день недели - и показывает, что каждый вносит. Это имеет значение, потому что ошибки cron почти всегда являются проблемой одного поля: правильное значение в неправильном столбце. 0 12 * * * (полдень каждый день) и 12 0 * * * (12:12 ежедневно... Нет, 00:12 ежедневно) - это один обмен. Вид "час: 0" - это явная маркировка, как вы поймаете этот своп за две секунды, а не две недели.
Поддержка диапазонов, шагов и списков
Реальные выражения сильно опираются на синтаксис оператора: 1-5 хребты, */10 ступеньки, 1,15 Списки и комбинации, как 0 8-18/2 * * 1,3,5. Анализатор обрабатывает все это, включая комбинированные формы, которые сбивают с толку читателей-людей. Шаговые значения в разных диапазонах - 8-18/2 значение " каждые 2 часа от 8 до 18" - законны, полезны и почти нечитаемы без инструментов. если вы ' когда-либо унаследовали кронаб, полный этих от ушедшего сисадмина, вы знаете, почему эта функция существует.
Строгая валидация пяти полей (включая то, что она не принимает)
Парсер принимает стандартные пятиполевые выражения и ничего больше. паста @daily и вы получаете ошибку - & quot;Ожидаемые 5 полей (минутный час день месяца день недели), получили 1 & quot; - не перевод То же самое @hourly, @weekly, и @reboot, йо- Это скорее пробел, а не принцип дизайна, и я бы предпочел так сказать, чем позволить вам узнать в середине отладки; сокращенные макросы достаточно распространены в реальных кронтабах, что они принадлежат инструменту. Пока они не зайдут, переводите вручную: @hourly есть 0 * * * *, @daily есть 0 0 * * *, @weekly есть 0 0 * * 0, @monthly есть 0 0 1 * *, @yearly есть 0 0 1 1 *, йо- @reboot не имеет эквивалента пяти полей вообще - это 't расписание, оно запускается один раз при запуске демона, и этот факт удивил многих людей, совершающих миграции из crontab.
Строгая окупаемость в другом месте. Выражение кварца с шестью полями отклоняется с числом полей вместо того, чтобы молча читать неправильно. Значения вне диапазона Назовите поле и юридическую область (Value 25 out of range for hour (allowed 0-23)). Обратные диапазоны, такие как 5-1 пойманы. И он принимает то, что содержат настоящие кронтабы: названия месяца и дня (JAN, SUN)) 7 Как второе написание воскресенья и Vixie 5/15 Форма Значение "Каждые 15, начиная с 5". Стоит знать, пока вы переводите эти макросы вручную: @daily работа на сервере срабатывает в тот же момент - полночь - так что сорок из них - ночной всплеск нагрузки Я разбрасываю свои по нечетным минутам (17 3 * * *, 43 4 * * *) именно по этой причине.
Обработка на стороне клиента
Парсер полностью работает в вашем браузере. Ничто не загружается, не загружается и не хранится. Это звучит как шаблонный язык конфиденциальности, пока вы не помните, что на самом деле содержат Crontabs: ваш резервный график, ваш биллинговый тайминг, точную минуту, в которой ваша служба безопасности сканирует пожар. Планирование инфраструктуры — это разведывательные данные. Держать его подальше от серверов других людей — это не паранойя, просто не создавая проблемы там, где никто не должен существовать.
Как использовать парсер Cron
Шаг 1: Вставьте или введите свое выражение
откройте синтаксический анализатор и опустите выражение - из файла crontab, a schedule: Блок в рабочем процессе действий GitHub, манифесте cronjob Kubernetes или Laravel ->cron() звонок Стандартный пятиполе синтаксис работает как есть; @daily И его братья и сестры этого не делают, поэтому сначала расширите их на пять полей. Затем нажмите Parse. Если вы начинаете с нуля, а не декодировать, то кнопки предустановки (каждые минуты, почасовая, ежедневная, 9:00, 1-го месяца) загружают рабочее выражение, которое можно изменить по полям, повторно разбирая по мере прохождения.
Шаг 2: Прочитайте перевод обратно
Это шаг люди пропускают и должны't. Прочитать простой английский вывод и сравнить его с предложением в вашей голове. если вы написали выражение намереваясь "каждый понедельник в 9 AM & quot; и в обратном обращении написано & quot;В 09:00 в день месяца 1 & quot; - поздравляю, вы только что поймали классический обмен столбцами до производства сделал.The readback это ваш единичный тест.
Шаг 3: Проверьте следующее время выполнения
Проверьте пять предстоящих казней. Приходят ли даты туда, куда вы ожидаете? Первый забег сегодня вечером, завтра или в следующем месяце? Обратите внимание на разрыв между пробегами - неуместный */ Шаг превращает «каждые 6 часов» в «каждую минуту каждого 6-го часа» (* */6 * * * против 0 */6 * * *), и пять пробежек в одну минуту с интервалом в шесть часов трудно не заметить. Пустой список означает, что расписание никогда не может срабатывать.
Шаг 4: Учет TimeZone перед развертыванием
Парсер говорит вам когда относительно часов; ваш планировщик решает чей часы Перед развертыванием подтвердите, какой часовой пояс использует исполняющая система. Действия GitHub: всегда UTC, без исключений. Серверы: на что бы ни настроена ОС, часто UTC в облачных ящиках. Laravel: Timezone вашего приложения, если вы не цепите ->timezone(), йо- Перевести следующее время выполнения через Конвертер времени отметки времени Если вам нужно увидеть его в вашей местной зоне или клиента.
Техническое глубокое погружение: как на самом деле работают выражения cron
Формат из пяти полей происходит от Unix cron, стандартизированного на практике Paul Vixie's cron реализации в конце 1980-х - тот, который задокументирован в crontab(5) И все еще отправляем, в форме потомка, в большинстве систем Linux сегодня. Поля слева направо:
| поле | Допустимые значения | банкноты |
|---|---|---|
| мелкий | 0–59 | |
| час | 0–23 | 24-часовые часы, 0 полночь |
| день месяца | 1–31 | Остерегайтесь месяцев без 31-го |
| месяц | 1–12 или январь–декабрь | В Vixie Cron разрешены имена |
| день недели | 0–7 или вс-сб | 0 и 7 оба в воскресенье |
Каждое поле принимает * (любое значение), списки (1,15), диапазоны (1-5), и шагов (*/10 или 20-59/5). Это's вся грамматика. Сложность равна 't в синтаксисе - it's в трех поведенческих причудах.
Причуда один: ноль дня недели. на crontab(5), и 0, и 7 означают воскресенье Некоторые более старые или более строгие реализации принимают только 0. Quartz - Java-планировщик, используемый Дженкинсом и половиной корпоративного программного обеспечения - числа дней 17, начиная с воскресенье, так кварц 2 Понедельник, пока Кронтаб 2 ВТОРНИК. Если вы когда-нибудь переносите расписание между системами, это незаметно подождет. Всегда разбирайте, никогда не расшифровывайте.
Причуда два: день месяца или день недели. Вот тот, кого почти никто не знает, пока не укусит их. когда оба Поля дня месяца и дня недели ограничены (ни *), Vixie Cron запускает работу, когда либо совпадения - ИЛИ, а не И. Так 0 0 13 * 5 это означает «пятница 13-го». Это означает «каждую 13-е месяца и каждую пятницу». crontab(5) И это глубоко нелогично. Если вам действительно нужна «пятница 13-го», вам нужна проверка даты на стороне сценария или планировщик с более богатым синтаксисом.
Причуда 3: часовые пояса и летнее время. У Крона нет поля Timezone. Выражение интерпретируется в местном времени планировщика, что бы это ни было. Два конкретных последствия:
- Запускает действия GitHub
schedule:Триггеры в UTC, полный останов. рабочий процесс, запланированный на0 9 * * *работает в 9 утра по всемирному координированному времени - 4 или 5 утра в Нью-Йорке в зависимости от сезона, потому что UTC не соблюдает летнее время 't соблюдает летнее время, но ваша целевая аудитория и часы #39;s соблюдают. Ваш "9 утра ежедневный отчет и котировка; дрейфует на час два раза в год, если вы не настроите рабочий процесс или не обработаете его в коде. - На серверах установлена зона наблюдения за DST, одну ночь в год 02:00–03:00 часа не существует, и одну ночь это происходит дважды. Задание, запланированное на 02:30, либо пропускает, либо двойной срабатывает в зависимости от реализации. Скучно, правильно исправить: запланировать критические задания вне 01:00–03:00 local или запустить серверы в UTC. Я делаю оба.
расширенные форматы. Кварц использует шесть или семь полей (поле для начального секунды и дополнительный год с задержкой), а также дополнительные операторы, такие как L (последний), W (ближайший будний день) и # (n-й будний день месяца).Некоторые crons поддерживают ведущее поле секунд тоже. если ваше выражение имеет шесть полей и вы ' не уверены, какой это диалект, вставить его в парсер - выражение из шести полей, интерпретируемое как пять-поле, будет производить явно неправильный вывод, который сам по себе является диагностическим. и @reboot, странная утка специальных строк, не является расписанием: она работает один раз в стартапе Daemon, что на современных системах означает «всякий раз, когда коробка перезагружается», — факт, который удивил многих людей, запускающих миграцию базы данных из Crontab.
Для более широкого тура по утилиты разработчиков, которые сочетаются с планировочными работами, Руководство по инструментам кодирования Покрывает весь набор инструментов.
Общие варианты использования
Отладка записи планировщика Laravel
Планировщик Laravel's бегло обматывает крона - ->dailyAt('03:00'), ->weeklyOn(1, '8:00')- но аварийный люк, ->cron('*/5 * * * 1-5'), это необработанный синтаксис crontab, и там попадают сложные расписания. Система Crontab работает schedule:run Каждую минуту, и Ларавель внутренне решает, что причитается. Когда запланированная команда не срабатывает, мой первый шаг — вставка ->cron() Введите в синтаксический анализатор, чтобы подтвердить, что это означает, что в комментариях выше он утверждает. Примерно в половине случаев это не так. Другая половина, ошибка - это часовой пояс: приложение установлено на UTC Пока разработчик полагал местное время. Парсер разрешает первый случай в секундах и указывает пальцем на второй.
Распутывание WP-Cron на сайтах WordPress
WordPress поставляется с wp-cron, который вообще является 't cron - it's псевдопланировщиком, который копирует посещения страниц, поэтому сайт с низким трафиком и #39;s "hourly" работа может выполняться каждые четыре часа, а сайт с высоким трафиком платит небольшой налог за каждый запрос. В течение лет моего WP Adminify это создавало постоянный поток " запланированные публикации 't публикация и котировки; отчеты. Стандартным исправлением является отключение wp-cron (стандартное исправление - отключение wp-cron)DISABLE_WP_CRON) и запуск wp-cron.php с реального сервера crontab - в этот момент вы ' пишете реальные выражения cron, обычно */5 * * * *, и парсер зарабатывает, продолжая проверять их. Если вы запускаете WordPress в любом масштабе, эту миграцию стоит сделать на этой неделе, а не когда-нибудь.
Проверка расписаний действий GitHub
Расписания CI тихо сбой: ночная сборка, которая перестает работать, никого не публикует. При написании schedule: триггер, я анализирую выражение, смотрю на время следующего запуска, затем мысленно добавляю смещение UTC. Две дополнительные детали, специфичные для Действий: расписания выполняются только в ветке по умолчанию, а запуски могут быть задержаны или исключены в периоды высокой нагрузки - GitHub' в собственных документах так и говорится. Если имеет значение точное время, то действия, запускаемые cron, являются неправильным инструментом; если приблизительное время в порядке, по крайней мере, сделайте приблизительное время правильный Примерное время.
Аудит унаследованного Crontab
На каждом долгоживущем сервере накапливается кронтаб, написанный людьми, которые там больше не работают. ходячий crontab -l и вставка каждой строки через синтаксический анализатор - это самый быстрый аудит, который я знаю: в течение десяти минут у вас есть простой английский список расписаний, и вы почти всегда найдете хотя бы одну работу, выполняющую то, что никто не помнил - резервную копию, выполняемую дважды, сценарий очистки, который никогда не соответствовал тому дню, который должен был быть, а * * * * * это должно было быть 0 * * * * Забивание API шестьдесят раз в час. При сравнении старого кронтата с новым во время миграции Инструмент текстового дифференциала Наряду с парсером обзор делает обзор механическим.
Расписание Kubernetes Cronjobs
K8S cronjobs используют стандартный синтаксис с пятью полями и, начиная с 1.27, поддерживают явный timeZone поле - подлинное улучшение по сравнению с классическим cron. рабочий процесс синтаксического анализатора тот же: проверить выражение, проверить следующие прогоны, затем подтвердить startingDeadlineSeconds а concurrencyPolicy Покрывайте режимы отказа, которые сам Cron не использует. Выражение может быть идеальным, и задание все еще накапливается, если медленный запуск перекрывает следующий триггер; парсер правильно расписан, чтобы вы могли вместо этого потратить свое внимание на эти операционные настройки.
Крон диалекты по сравнению
| Викси Крон / Кронтаб | Действия GitHub | кварц | Планировщик Ларавель | Таймеры системных | |
|---|---|---|---|---|---|
| пороки | 5 | 5 | 6–7 (секунды, год) | 5 (через ->cron())) |
OnCalendar Синтаксис, а не Крон |
| нумерация в день | 0–7 (0 и 7 = солнце) | 0–6 (0 = солнце) | 1–7 (1 = солнце) | следует за Кронтабом | имена (Mon, Tue)) |
| часовой пояс | Системная локальная | Всегда UTC | настраиваемый | Часовой пояс приложения или ->timezone() |
Системная локальная или Timezone= |
| Специальные струны | @daily, @rebootи т.д. |
не поддерживается | не поддерживается | вместо этого свободно | OnBootSec=, календарь |
| секунды точности | нет | Нет (мин ~5 мин практично) | да | Нет (в минуту тика) | да |
| лучше для | Вакансии на сервер | CI/CD расписания | Экосистемы JVM | Приложения для Laravel | Современные сервисы Linux |
Когда использовать какие: crontab для простых заданий сервера, systemd таймеры, когда вы хотите вести журнал и обработку зависимостей бесплатно в современном Linux, планировщик фреймворков, когда задание все равно живет внутри вашего приложения, и Действия расписаны только для задач CI, которые терпят нечеткое время. Что бы вы ни выбрали, выражение из пяти полей - это lingua franca - вот почему парсер, который говорит на нем свободно, принадлежит вашим закладкам рядом с остальными вашими Набор инструментов для веб-разработчиков, йо-
часто задаваемые вопросы
Что такое синтаксический анализатор cron?
Анализатор выражений cron - это инструмент, который считывает синтаксис crontab */15 9-17 * * 1-5- и переводит его в описание расписания на простом английском языке, обычно вместе с предварительным просмотром следующего времени выполнения. Это позволяет вам проверить, что на самом деле делает расписание, прежде чем развертывать его, вместо того, чтобы обнаруживать неправильно прочитанное поле, когда задание срабатывает не в то время, когда оно находится в производстве.
Что означают пять полей в выражении cron?
Слева направо: минута (0–59), час (0–23), день месяца (1–31), месяц (1–12) и день недели (0–7, где 0–7 — 7 — 7 — воскресенье). Каждое поле принимает * Для любого значения, списки запятых, диапазоны дефиса и / Шаговые значения. поэтому 30 2 1 * * Средства 02:30 в первый день каждого месяца.
Почему моя работа cron работает в неподходящее время?
Две наиболее распространенные причины - это путаница часовых поясов и полей.Cron работает в планировщике's по местному времени - GitHub Actions всегда использует UTC, и многие облачные серверы тоже - так что задание, запланированное для & quot;9 AM & quot; может отключаться от часов настенных часов. другой классикой является замена полей, например, установка значения часа в столбце минут. Анализ выражения и проверка времени следующего запуска улавливает оба.
0 и 7 оба воскресенья в cron?
В Vixie cron и большинстве реализаций Linux да - the crontab(5) Man Page разрешает как 0, так и 7 в воскресенье. Но это не универсально: кварцевые числа 1–7 дней, начиная с воскресенья, а некоторые строгие парсеры отвергают 7. При перемещении выражений между системами повторно проверьте поле «День недели», а не предполагайте, что нумерация сохраняется.
Что делает 0 0 13 * 5 на самом деле сделать?
Не «пятница 13-го». Когда как в день, так и в день недели ограничены, стандартные кроны относятся к ним как к OR: работа работает каждый 13-й месяц а каждую пятницу. Это задокументировано поведение Викси Крона и одно из самых непонятых правил формата. Если вам нужна true и добавьте проверку даты внутри самого скрипта.
Как летнее время влияет на работу cron?
На серверах в часовых поясах, наблюденных за DST, задания, запланированные с 01:00 до 03:00, могут пропускать прогон (когда часы перескакивают вперёд) или бежать дважды (когда они падают назад), в зависимости от реализации. Самые безопасные шаблоны — это запуск серверов в UTC или планирование критических заданий за пределами этого окна. Обратите внимание, что планировщики на основе UTC, такие как действия GitHub, не пропускают прогоны, но местное время соответствует сменам на час два раза в год.
есть @daily то же, что и 0 0 * * *?
Да - @daily (и его синоним @midnight) расширяется точно 0 0 * * * В Викси Крона. Два оговорки. Во-первых, синтаксический анализатор Toolz.dev принимает только пять полей, поэтому вставьте 0 0 * * * а не @daily пока. Во-вторых, каждый @daily Работа срабатывает в одно и то же время, поэтому сервер со многими из них получает всплеск нагрузки в полночь. Распространение повседневных рабочих мест в ступнях и часах позволяет избежать этого громогласного стада.
Загружает ли синтаксический анализатор Toolz.dev cron мои выражения?
нет , синтаксический анализатор полностью запускается в вашем браузере - выражения анализируются на стороне клиента и никогда не отправляются на сервер, не регистрируются и не сохраняются. поскольку crontabs раскрывают операционные детали, такие как время резервного копирования и запуск счетов, их отключение от сторонних серверов является разумным по умолчанию, и вы можете подтвердить поведение самостоятельно в своем браузере и на вкладке "Сеть #39;s".
Прочтите его перед отправкой
Пять недель дайджеста электронные письма, прибывающие на день позже не является драматическим сбоем. Никто не вызывал у меня. Это 's именно то, что делает ошибки планирования дорогими: они не объявляют себя, они просто тихо делают неправильные вещи, пока клиент не упоминает об этом мимоходом. Привычка, которая исправила это для меня, - это 't дисциплина или лучшее воспоминание для полевого заказа - it's тридцатисекундный возврат. Вставьте выражение, прочитайте английское предложение, посмотрите на пять конкретных дат, затем разверните.
держать синтаксический анализатор рядом с инструментами, которые вы будете добывать в той же сессии отладки: Конвертер времени отметки времени Когда следующее время выполнения должно перемещаться между зонами (я написал Трапы UNIX что укусить тяжелее всего), Калькулятор разницы дат для интервалов проверки здравомыслия и Инструмент текстового дифференциала Когда вы сравниваете старый crontab с новым во время миграции. выше Руководство по инструментам кодирования просматривает, как набор сочетается друг с другом, и все работает на стороне клиента, что для файла, который точно документирует, когда срабатывают ваши резервные копии и выставление счетов, является единственным разумным по умолчанию.



