28

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

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

(мой акцент)

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

12 ответов12

36

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

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

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

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

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

6

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

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

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 (= пятница) месяца

5

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

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

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

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

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

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

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
0 9 1-7 * 1 * 

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

0

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

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

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

0 30 8 * 1/1 MON#1

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

0

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .