Виконувати роботу з крон у перший понеділок кожного місяця?


32

Я хотів би зайняти роботу з cron о 8.30 першого понеділка кожного місяця. Сторінка Вікіпедії "Крон" говорить

Хоча звичайно завдання виконується, коли всі поля специфікації часу / дати відповідають поточному часу та даті, є один виняток: якщо обидва "день місяця" та "день тижня" обмежені (не "*"), то або поле "день місяця" (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

Я запланував роботу, яку потрібно виконувати на четвертий понеділок кожного місяця о 16:00 наступним чином:

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

1

Наскільки я знаю, НЕ можна використовувати лише кронтаб, проте можна використовувати функцію обгортки, щоб вибрати правильний день із запису контакту «перші сім днів місяця»; дивіться це з вступу.

Сценарій обгортки був би

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

і вам потрібно запустити його (припустимо, що він називається wrapper.sh і доступний у всьому світі), використовуючи запис crontab

0 0 * * 1 wrapper.sh

дякую елемакі. Я подумав про подібне рішення, використовуючи якийсь додатковий код всередині завдання, яке запускається, змусивши його перевірити, чи це перший понеділок місяця всередині сценарію, а потім називати його щонеділі в 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"

Сценарій запустити, якщо сьогодні сьогодні, і для буднього дня, і для бажаного діапазону дат тижня, якщо обидва відповідають, то він повертає 0, інакше 1.

Перевірте код тут. https://github.com/xr09/cron-last-sunday


0

Я вважаю, що це вирішує проблему більш елегантно:

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

1
До! : "Якщо обидва поля обмежені (тобто не є *), команда буде виконуватися, коли будь-яке поле відповідає поточному часу."
symcbean

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

"або" означає будь-який з них, а не "обидва". це буде працювати щодня протягом перших 7 днів місяця.
мінус

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

0

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

0 30 8 * 1/1 MON#1

Сподіваюся, що це допомагає комусь іншому. Незважаючи на все, бажаю всім прекрасного дня. :-)


Це не крон, це, можливо, кварц
sivann

-1
0 9 1-7 * 1 * 

Це буде працювати кожного понеділка кожного місяця.


Відповідь прийнято, ваша відповідь краща, інша чи корисна у новій версії тощо
mic84
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.