Подтвердить что ты не робот

Как инструктировать cron выполнять работу каждую вторую неделю?

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

0 6 * * Tue

Но как сделать это "каждый второй вторник" (или, если хотите, каждую вторую неделю)? Я бы не хотел реализовывать какую-либо логику в script сам, но сохраняю определение только в cron.

4b9b3361

Ответ 1

Как насчет этого, он сохраняет его в crontab, даже если он не определен точно в первых пяти полях:

0 6 * * Tue expr `date +\%W` \% 2 > /dev/null || /scripts/fortnightly.sh

Ответ 2

Ответ

Измените логику cron во вторник, чтобы выполнять каждую вторую неделю с эпохи.

Зная, что есть 604800 секунд в неделю (игнорируя изменения DST и секунды прыжка, спасибо) и используя дату GNU:

0 6 * * Tue expr `date +\%s` / 604800 \% 2 >/dev/null || /scripts/fortnightly.sh

Помимо

Арифметика календаря расстраивает.

@xahtep ответ потрясающий, но, поскольку @Doppelganger отметил в комментариях, он не пройдет на определенных границах года. Ни одна из спецификаторов date "неделя года" может помочь здесь. Некоторое вторжение в начале января неизбежно повторит недельный паритет последнего вторника в предыдущем году: 2016-01-05 (% V), 2018-01-02 (% U) и 2019-01-01 (% W).

Ответ 3

ответ пиквера отлично. Однако это приводит к тому, что каждые две недели (начиная с эпохи) работает каждые две недели. Sh script. Если вам понадобится script для запуска в нечетные недели, вы можете немного настроить его ответ:

0 6 * * Tue expr \( `date +\%s` / 604800 + 1 \) \% 2 > /dev/null || /scripts/fortnightly.sh

Смена 1 на 0 приведет к ее возврату еще на недели.

Ответ 4

Может быть, немного тупой, но можно также создать две cronjobs, по одной на каждый первый вторник и на каждую третью.

Первая cronjob:

0 0 8 ? 1/1 TUE#1 *

Вторая cronjob:

0 0 8 ? 1/1 TUE#3 *

Не уверен в синтаксисе здесь, я использовал http://www.cronmaker.com/, чтобы сделать это.

Ответ 5

Как насчет каждой третьей недели?

Здесь мое предложение:

0 6 * * Tue expr `date +\%W` \% 3 == 0 > /dev/null || /scripts/fortnightly.sh

... или...

0 6 * * Tue expr `date +\%W` \% 3 == 1 > /dev/null || /scripts/fortnightly.sh

... или, конечно...

0 6 * * Tue expr `date +\%W` \% 3 == 2 > /dev/null || /scripts/fortnightly.sh

... в зависимости от поворота недели.

Ответ 6

Если вы хотите каждый вторник только второй недели:

00 06 * * 2 # 2

Ответ 7

Я обнаружил некоторые дополнительные ограничения вышеприведенных подходов, которые могут сбой в некоторых случаях. Например, рассмотрим:

@xahtep и @Doppelganger обсудили проблемы, используя %W на определенных границах года выше.

Ответ на

@pilcrow до некоторой степени зависит от этого, однако он тоже не будет работать на определенных границах. Ответы на эту и другие связанные темы используют количество секунд в день (против недели), которые также не работают по определенным границам по тем же причинам.

Это связано с тем, что эти подходы зависят от времени UTC (дата +% s). Рассмотрим случай, когда мы выполняем работу в 1 утра и 10 вечера каждый второй вторник.

Предположим, что GMT-2:

  • 1 час локального времени = 11 вечера UTC вчера
  • 10 вечера по местному времени = 8 вечера UTC сегодня

Если мы проверяем только один раз каждый день, это не будет проблемой, но если мы будем проверять несколько раз - или если мы близки к времени UTC, а переход на летнее время происходит, script не будет подумайте, что они будут в тот же день.

Чтобы обойти это, нам нужно рассчитать смещение от UTC на основе нашего локального часового пояса, а не UTC. Я не мог найти простой способ сделать это в BASH, поэтому я разработал решение, которое использует быстрый один лайнер в Perl для вычисления смещения от UTC в секундах.

В этом script используется дата +% z, которая выводит локальный часовой пояс.

Bash script:

TZ_OFFSET=$( date +%z | perl -ne '$_ =~ /([+-])(\d{2})(\d{2})/; print eval($1."60**2") * ($2 + $3/60);' )
DAY_PARITY=$(( ( `date +%s` + ${TZ_OFFSET} ) / 86400 % 2 ))

затем, чтобы определить, является ли день четным или нечетным:

if [ ${DAY_PARITY} -eq 1 ]; then
...
else
...
fi

Ответ 8

Cron предоставляет "любой другой" синтаксис "/2". Просто следуйте за полем соответствующего времени с "/2", и он будет выполнять cronjob "в другое время". В вашем случае...

0 6 * * Tue/2

Вышеуказанное должно выполняться каждый второй вторник.

Ответ 9

Синтаксис "/2" не совпадает с рабочим днем. Поэтому мой добавленный к умному выше просто используется 1,15 на MonthDay.

0 6 1,15 * */scripts/fornightly.sh > /dev/null 2 > & 1

Ответ 10

Почему не что-то вроде

0 0 1-7,15-21,29-31 * 5

Это уместно?