it-swarm-ru.tech

Как я могу сказать cron запускать команду через день (нечетное / четное)

При настройке cron для запуска команды через день, используя поле "День месяца", например:

1 22 */2 * * COMMAND

он запускается каждый раз, когда день месяца нечетный: 1,3,5,7,9 и так далее.

Как настроить cron для работы в дни месяца, которые даже равны 2,6,8,10 и т.д. (Без буквального указания этого, что проблематично, поскольку в каждом месяце разное количество дней в месяце)?

46
freddie

Синтаксис, который вы пробовали, на самом деле неоднозначен. В зависимости от того, сколько дней в месяце, некоторые месяцы будут работать в нечетные дни, а некоторые - в четные. Это потому, что способ расчета рассчитывает общее количество возможностей и разделяет их. Вы можете переопределить это поведение strage-ish, вручную указав диапазон дней и используя нечетное или четное количество дней. Поскольку четные дневные сценарии никогда не будут выполняться в 31-й день более длинных месяцев, вы ничего не потеряете, используя 30 дней в качестве основы для четных дней, и, указав специально для деления, как если бы было 31 день, вы можете вызвать нечетные исполнение.

Синтаксис будет выглядеть так:

# Will only run on odd days:
0 0 1-31/2 * * command

# Will only run on even days:
0 0 2-30/2 * * command

Ваше беспокойство по поводу того, что месяцы не имеют одинакового количества дней, здесь не важно, потому что ни у одного месяца нет БОЛЬШЕ дней, чем этот, а для плохого февраля диапазон дат просто не будет совпадать с последним днем ​​или двумя, но это не принесет вреда. имея это в списке.

Единственный "уловка" для этого подхода состоит в том, что если вы находитесь в нечетном дневном цикле, в следующие месяцы с 31 днем ​​ваша команда будет также выполняться в первом месяце. Точно так же, если вы форсируете четный цикл, каждый високосный год будет вызывать один трехдневный цикл в конце февраля. Вы не можете обойти тот факт, что любой регулярный паттерн "каждый второй день" не всегда будет приходиться на четные или нечетные дни в каждом месяце, и как бы вы ни принудили это сделать, у вас либо будет дополнительный прогон, либо вы пропустите пробежку между месяцы с несоответствующим количеством дней.

64
Caleb

Я думаю, что есть возможность использовать день года, например, так:

# for odd days
test $(((`date +%j` % 2))) != 0 && command

# for even days
test $(((`date +%j` % 2))) == 0 && command

Протестировано для систем Unix и Linux.

2
Jordi

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

Создание простого файла состояния с указанием времени последнего запуска и последующего сравнения будет очень легко работать.

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

1
Klas Mattsson

Давайте каждый день проверять, является ли это "другим" :-) (требуется программа bc)

0 0 * * * test $(echo `date +%s` / 86400 % 2 == 0 |bc) -eq 0 && command

(Я не уверен, что код отображается правильно. date +%s часть находится между обратными апострофами.)

1
user37264