Как работают Cron "Шаги"?

Я столкнулся с ситуацией, когда работа cron, о которой я думал, работала каждые 55 минут, на самом деле работает через 55 минут после часа и в верхней части часа. На самом деле это не работа cron, но это приложение планирования PHP, которое использует синтаксис cron.

Когда я прошу это приложение планировать работу каждые 55 минут, он создает линию crontab, как показано ниже.

*/55 * * * *

Эта строка crontab заканчивается не, выполняющей задание каждые 55 минут. Вместо этого работа проходит через 55 минут после часа и в верхней части часа. Я не хочу этого. Я запустил это, хотя cron tester, и он проверяет, что нежелательное поведение - правильное поведение cron.

Это приводит меня к тому, чтобы посмотреть, что означает /. Когда я посмотрел на cron manual, я узнал, что косая черта обозначена как "шаги", но сама инструкция немного нечеткая, что означает

Значения шагов могут использоваться в сочетании с диапазонами. После диапазона с "<number>" указывает пропускание значения числа через диапазон. Например, в поле часов можно использовать "0-23/2", чтобы указать выполнение команды каждый час (альтернатива в стандарте V7 "0,2,4,6,8,10,12,14,16,18,20,22"). Шаги также разрешены после звездочки, поэтому, если вы хотите сказать" каждые два часа ", просто используйте" */2".

Описание руководства ( "указывает пропуски значения числа через диапазон" ) немного расплывчато, а пример "каждые два часа" мало вводит в заблуждение (что, вероятно, привело к ошибке в приложении)

Итак, два вопроса:

  • Как программа unix cron использует информацию о шаге (число после косой черты), чтобы решить, следует ли пропустить выполнение задания? (модульное деление? Если да, то на чем? С какими условиями, решающими "истинный" прогон, а какие решения нет? Или это что-то еще?)

  • Можно ли настроить задание unix cron для запуска каждой "N" минут?

Ответ 1

Значения шагов могут использоваться в сочетании с диапазонами. Следуя диапазону с "<number>" указывает пропускание значения числа через диапазон. Для Например, "0-23/2" может использоваться в поле часов для указания команды выполнение каждого другого часа (альтернатива в стандарте V7 "0,2,4,6,8,10,12,14,16,18,20,22" ). Шаги также разрешаются после звездочка, поэтому, если вы хотите сказать "каждые два часа", просто используйте "*/2".

"Диапазон", на который ссылается здесь, - это диапазон, заданный до /, который является поддиапазоном диапазона раз для конкретного поля. Первое поле указывает минуты в течение часа, поэтому */... указывает диапазон от 0 до 59. Первое поле */55 указывает все минуты (в пределах диапазона 0-55), которые кратно 55 - то есть 0 и Через 55 минут после каждого часа.

Аналогично, 0-23/2 или */2 во втором (часовом) поле указывает все часы (в пределах диапазона 0-23), которые кратно 2.

Если вы укажете начало диапазона, отличное от 0, число (скажем N) после / указывает каждую минуту Nth минута/час/и т.д. на нижней границе диапазона. Например, 3-23/7 во втором поле означает каждый 7-й час, начинающийся в 03:00 (03:00, 10:00, 17:00).

Это лучше всего работает, когда промежуток, который вы хотите, равномерно распределяется на следующую более высокую единицу времени. Например, вы можете легко указать событие, которое должно происходить каждые 1, 2, 3, 4, 5, 6, 10, 12, 15, 20 или 30 минут или каждые 1, 2, 3, 4, 6 или 12 ч. (Спасибо вавилонянам за выбор единиц времени с таким количеством приятных делителей.)

К сожалению, cron не имеет понятия "каждые 55 минут" в течение времени, превышающего час.

Если вы хотите запускать задание каждые 55 минут (например, в 00:00, 00:55, 01:50, 02:45 и т.д.), вам придется делать это косвенно. Один из подходов - планировать запуск script каждые 5 минут; script затем проверяет текущее время и выполняет его работу только один раз в 11 раз, когда он вызывал.

Или вы можете использовать несколько строк в вашем файле crontab для запуска той же работы в 00:00, 00:55, 01:50 и т.д. - за исключением того, что день не кратен 55 минут. Если вы не возражаете, чтобы иметь более длинный или более короткий интервал один раз в день, неделю или месяц, вы можете написать программу для создания большого crontab с таким количеством записей, сколько вам нужно, все работают с той же командой в указанное время.

Ответ 2

Существует еще один инструмент, названный at этом отношении. Его можно использовать вместо cron для достижения того, чего хочет автор темы. Насколько я помню, он предустановлен в OS X, но не входит в состав некоторых дистрибутивов Linux, таких как Debian (просто apt install at).

Он запускает задание в определенное время суток, и это время может быть рассчитано с использованием сложной спецификации. В нашем случае можно использовать следующее:

Вы также можете указать время, например, сейчас + подсчитать единицы времени, где единицами времени могут быть минуты, часы, дни или недели, и вы можете указать, чтобы выполнить задание сегодня, добавив суффикс времени к сегодняшнему дню и запустив задание завтра. добавив время к завтрашнему дню.

Сценарий every2min.sh выполняется каждые 2 минуты. Это задерживает следующее выполнение каждый раз, когда экземпляр работает:

#!/bin/sh
at -f ./every2min.sh now + 2 minutes
echo "$(date +'%F %T') running..." >> /tmp/every2min.log

Какие выводы

2019-06-27 14:14:23 running...
2019-06-27 14:16:00 running...
2019-06-27 14:18:00 running...

Поскольку at не знает о единице "секунд", время выполнения будет округлено до полной минуты после первого запуска. Но для данной задачи (с интервалом 55 минут) это не должно быть большой проблемой.

Там также могут быть соображения безопасности

Для команд at и batch команды считываются из стандартного ввода или файла, указанного с помощью опции -f, и выполняются. Рабочий каталог, среда (за исключением переменных BASH_VERSINFO, DISPLAY, EUID, GROUPS, SHELLOPTS, TERM, UID и _) и umask сохраняются со времени вызова.

Это самый простой способ запланировать запуск чего-либо каждые X минут, которые я видел до сих пор.