Ответ 1
Как насчет этого, он сохраняет его в crontab
, даже если он не определен точно в первых пяти полях:
0 6 * * Tue expr `date +\%W` \% 2 > /dev/null || /scripts/fortnightly.sh
Я хотел бы запустить задание через cron, который будет выполняться каждый второй вторник в указанное время суток. Для каждого вторника легко:
0 6 * * Tue
Но как сделать это "каждый второй вторник" (или, если хотите, каждую вторую неделю)? Я бы не хотел реализовывать какую-либо логику в script сам, но сохраняю определение только в cron.
Как насчет этого, он сохраняет его в crontab
, даже если он не определен точно в первых пяти полях:
0 6 * * Tue expr `date +\%W` \% 2 > /dev/null || /scripts/fortnightly.sh
Измените логику 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).
ответ пиквера отлично. Однако это приводит к тому, что каждые две недели (начиная с эпохи) работает каждые две недели. Sh script. Если вам понадобится script для запуска в нечетные недели, вы можете немного настроить его ответ:
0 6 * * Tue expr \( `date +\%s` / 604800 + 1 \) \% 2 > /dev/null || /scripts/fortnightly.sh
Смена 1 на 0 приведет к ее возврату еще на недели.
Может быть, немного тупой, но можно также создать две cronjobs, по одной на каждый первый вторник и на каждую третью.
Первая cronjob:
0 0 8 ? 1/1 TUE#1 *
Вторая cronjob:
0 0 8 ? 1/1 TUE#3 *
Не уверен в синтаксисе здесь, я использовал http://www.cronmaker.com/, чтобы сделать это.
Как насчет каждой третьей недели?
Здесь мое предложение:
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
... в зависимости от поворота недели.
Если вы хотите каждый вторник только второй недели:
00 06 * * 2 # 2
@xahtep и @Doppelganger обсудили проблемы, используя
Ответ на%W
на определенных границах года выше.@pilcrow до некоторой степени зависит от этого, однако он тоже не будет работать на определенных границах. Ответы на эту и другие связанные темы используют количество секунд в день (против недели), которые также не работают по определенным границам по тем же причинам.
Это связано с тем, что эти подходы зависят от времени UTC (дата +% s). Рассмотрим случай, когда мы выполняем работу в 1 утра и 10 вечера каждый второй вторник.
Предположим, что GMT-2:
Если мы проверяем только один раз каждый день, это не будет проблемой, но если мы будем проверять несколько раз - или если мы близки к времени UTC, а переход на летнее время происходит, script не будет подумайте, что они будут в тот же день.
Чтобы обойти это, нам нужно рассчитать смещение от UTC на основе нашего локального часового пояса, а не UTC. Я не мог найти простой способ сделать это в BASH, поэтому я разработал решение, которое использует быстрый один лайнер в Perl для вычисления смещения от UTC в секундах.
В этом script используется дата +% z, которая выводит локальный часовой пояс.
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
Cron предоставляет "любой другой" синтаксис "/2". Просто следуйте за полем соответствующего времени с "/2", и он будет выполнять cronjob "в другое время". В вашем случае...
0 6 * * Tue/2
Вышеуказанное должно выполняться каждый второй вторник.
Синтаксис "/2" не совпадает с рабочим днем. Поэтому мой добавленный к умному выше просто используется 1,15 на MonthDay.
0 6 1,15 * */scripts/fornightly.sh > /dev/null 2 > & 1
Почему не что-то вроде
0 0 1-7,15-21,29-31 * 5
Это уместно?