Запускать работу cron в первый понедельник каждого месяца?


32

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

Хотя обычно задание выполняется, когда все поля спецификации времени / даты соответствуют текущему времени и дате, есть одно исключение: если и «день месяца», и «день недели» ограничены (не «*»), то либо поле «день месяца» (3) или поле «день недели» (5) должны соответствовать текущему дню.

(мой акцент)

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


slhck - это звучит как хорошее решение - не могли бы вы развернуть его в ответ с полным кодом? тогда я отмечу это как правильный :)
Макс Уильямс

Ответы:


39

Вы можете поместить условие в фактическую команду crontab:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Теперь, если это условие выполняется в один из первых семи дней месяца, у вас есть первый понедельник. Обратите внимание, что в crontab процентный синтаксис необходимо экранировать, хотя:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Замените echoкоманду фактической командой, которую вы хотите запустить. Я нашел аналогичный подход тоже.


на самом деле, slhck, я говорил слишком рано - это не работает в моем crontab: похоже, у него проблемы с датой теста по какой-то причине. Это работает в командной строке, [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"как и [ $(date '+%a') = "Mon" ] && echo "It's Monday" Но, но в crontab, похоже, не удается в этом тесте. Я не могу получить ни одного полезного отзыва от cron: я пытаюсь [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1зафиксировать любой вывод ошибок в журнал, но это тоже не работает: /
Макс Уильямс

Гектометр Можете ли вы проверить правильность dateвывода? Например, просто cronзапустите команду, которая выводит это в файл: date '+%a' > ~/datetest 2>&1- затем проверьте, привела ли это к правильной строке для сравнения.
Slhck

1
Я нашел эту проблему - процент в +%aнеобходимом побеге , когда он был в кронтабе, то есть линии , необходимых для таких: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Если бы вы могли обновить свой ответ, это было бы полезно для будущих читателей :) Еще раз спасибо - Макс
Макс Уильямс

О, теперь я понимаю, почему. Рад, что это работает сейчас, спасибо за попытку!
Slhck

15

У меня есть компьютер с языком на испанском языке, поэтому этот подход не работает для меня, потому что понедельник меняется на лун

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

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"

+1 ¡Muy bien, сеньор!
JakeGould

1
Gracias ¡Pura Vida! ; D
cumanacr

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

7

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

Запустите первый понедельник месяца:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

то есть, если месяц 1 неделя назад не совпадает с текущим месяцем, то мы находимся в 1-й день 1 (= понедельник) месяца.

Точно так же на третью пятницу

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

т.е. если месяц 3 недели назад отличается от текущего месяца, то мы находимся на 3-й день 6 (= пятница) месяца


6-й день недели - суббота, а не пятница.
Роберт

4

Я запланировал работу на 4-й понедельник каждого месяца в 16:00 следующим образом:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt

1

Насколько я знаю, это невозможно при использовании только crontab, однако можно использовать функцию-обертку, чтобы выбрать правильный день из записи contab «первые семь дней месяца»; увидеть это из записи.

Скрипт-обёртка будет

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

и вам нужно будет запустить его (при условии, что он называется wrapper.sh и доступен глобально), используя запись crontab

0 0 * * 1 wrapper.sh

спасибо elemaki. Я подумал о подобном решении, использующем некоторый дополнительный код внутри запускаемой задачи, заставляющий его проверять, является ли это первый понедельник месяца внутри скрипта, и затем вызывал его каждый понедельник в crontab. Это рубиновый скрипт, поэтому легко проверить день недели. Но я надеялся, что будет только crontab.
Макс Уильямс

1

На Solaris 10 мне пришлось отформатировать условие следующим образом:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"

1

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

30 8 * * 1 [`date +\%d` -le 07] && <job>

Выше должно работать на вас.


+1 больше успеха, чем бежать за первую неделю и проверить на понедельник. :-)
xmedeko

1

Я рекомендую использовать

"$(/bin/date '+%\w')" = "1"

вместо того

"$(date '+\%a')" = "Mon"

чтобы избежать языковой проблемы.


0

Я сделал общее решение для такого рода проблем, оно работает для первого, второго, третьего ... последнего дня недели месяца.

Вы можете использовать это так:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

Скрипт run-if-today проверяет как день недели, так и желаемый диапазон дат недели, если оба совпадают, возвращается 0, в противном случае - 1.

Проверьте код здесь. https://github.com/xr09/cron-last-sunday


0

Я считаю, что это решает проблему более элегантно:

30 8 1-7 * 1 /run/your/job.sh

1
Doh! : «Если оба поля ограничены (т. Е. Не *), команда будет запущена, когда любое из полей будет соответствовать текущему времени».
Symcbean

Также в феврале (тот, который заканчивается 28-го), он не будет запускаться каждые 4 года.
igraczech

«либо» означает любой из них, а не «оба». Это будет работать каждый день в течение первых 7 дней месяца.
минус

Эта строка будет запускать команду с первого по седьмое каждого месяца, а также каждый понедельник
Томаш Якуб Руп

0

Поскольку я интерпретирую свои выражения cron с помощью php и js, я не могу использовать bash. В конце концов я обнаружил , что это на самом деле возможно только с хронами:

0 30 8 * 1/1 MON#1

Надеюсь, это поможет кому-то еще. Несмотря на это, я желаю вам всем прекрасного дня. :-)


Это не Cron, это, возможно, кварц
Сиванн

-1
0 9 1-7 * 1 * 

Это будет работать каждый понедельник каждого месяца.


Ответ принят, ваш ответ лучше, отличается или полезен в новой версии и т. Д.
mic84
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.