Czy uruchomić cron w pierwszy poniedziałek każdego miesiąca?

32

Chciałbym uruchomić pracę z cron o 8.30 w pierwszy poniedziałek każdego miesiąca. Strona Wikipedii cron mówi

Chociaż normalnie zadanie jest wykonywane, gdy wszystkie pola specyfikacji godziny / daty odpowiadają bieżącej godzinie i dacie, istnieje jeden wyjątek: jeśli zarówno „dzień miesiąca”, jak i „dzień tygodnia” są ograniczone (nie „*”), wówczas albo pole „dzień miesiąca” (3) lub pole „dzień tygodnia” (5) muszą być zgodne z bieżącym dniem.

(mój nacisk)

Czy to oznacza, że ​​nie mogę zrobić pierwszego poniedziałku miesiąca, mogę zrobić tylko pierwszy (lub jakikolwiek inny) dzień miesiąca? Nie mogę wymyślić sposobu na obejście tego.

Max Williams
źródło
slhck - to brzmi jak dobre rozwiązanie - czy miałbyś coś przeciwko rozszerzeniu go na odpowiedź z pełnym kodem? wtedy zaznaczę to jako poprawne :)
Max Williams

Odpowiedzi:

39

Możesz umieścić warunek w rzeczywistym poleceniu crontab:

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

Jeśli ten warunek jest spełniony przez jeden z pierwszych siedmiu dni w miesiącu, masz pierwszy poniedziałek. Zauważ, że w crontab składnia procentowa musi być zmieniona:

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

Zastąp echopolecenie rzeczywistym poleceniem, które chcesz uruchomić. Znalazłem też podobne podejście .

slhck
źródło
właściwie, slhck, mówiłem zbyt wcześnie - to nie działa w moim crontabie: z jakiegoś powodu wydaje się, że ma problem z testem daty. Działa to [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"tak jak w wierszu poleceń. [ $(date '+%a') = "Mon" ] && echo "It's Monday" Ale w crontab wydaje się, że zawodzi podczas tego testu. Nie mogę również uzyskać żadnej przydatnej informacji zwrotnej od crona: próbuję [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1przechwycić dane wyjściowe błędu w dzienniku, ale to też nie działa: /
Max Williams
Hm Czy możesz sprawdzić, czy dane datewyjściowe są prawidłowe? Na przykład po prostu cronuruchom polecenie, które wypisuje to do pliku: date '+%a' > ~/datetest 2>&1- a następnie sprawdź, czy otrzymano odpowiedni ciąg znaków do porównania.
slhck
1
Znalazłem problem - procent w +%apotrzebnej ucieczki, gdy był w crontab, czyli linii musiał być to: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Gdybyś mógł zaktualizować swoją odpowiedź, byłoby to pomocne dla przyszłych czytelników :) Jeszcze raz dziękuję - max
Max Williams
Och, teraz rozumiem dlaczego. Cieszę się, że teraz działa, dziękuję za wypróbowanie!
slhck
15

Mam komputer z językiem hiszpańskim, więc to podejście nie działa dla mnie, ponieważ mon zmienia się na lun

Inne języki również zawiodłyby, więc wprowadziłem niewielką zmianę w zaakceptowanej odpowiedzi, która usuwa barierę językową:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"
cumanacr
źródło
+1 ¡Muy bien, señor!
JakeGould,
1
Gracias ¡Pura vida! ; D
cumanacr
To powinna być zaakceptowana odpowiedź. Mam holenderskie ustawienia regionalne, które używają również różnych nazw w dni powszednie. Używanie liczb wydaje się również czystsze niż porównywanie ciągów w celu ustalenia dnia tygodnia.
0ne_Up
7

Jest mi łatwiej, kiedy nie ma potrzeby obsługi numerów dziennych.

Uruchom w pierwszy poniedziałek miesiąca:

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

tzn. jeśli miesiąc 1 tydzień temu nie jest taki sam jak bieżący miesiąc, to jesteśmy w pierwszym dniu 1 (= poniedziałek) miesiąca.

Podobnie w trzeci piątek

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

tj. jeśli miesiąc 3 tygodnie temu jest inny niż bieżący miesiąc, to jesteśmy w trzecim dniu 6 (= piątek) miesiąca

joel
źródło
Dzień 6 tygodnia to sobota, a nie piątek.
Robert
4

Zaplanowałem uruchomienie zadania w 4. poniedziałek każdego miesiąca o 16:00 w następujący sposób:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt
Abhijit Mapgaonkar
źródło
1

O ile mi wiadomo, NIE jest możliwe używanie tylko crontab, jednak można użyć funkcji otoki, aby wybrać właściwy dzień z wpisu „pierwsze siedem dni miesiąca”; zobacz to od wpisu.

Skrypt opakowania byłby

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

i musisz go uruchomić (zakładając, że nazywa się wrapper.sh i jest dostępny na całym świecie) przy użyciu wpisu crontab

0 0 * * 1 wrapper.sh
elemakil
źródło
dzięki elemaki. Pomyślałem o podobnym rozwiązaniu, używając dodatkowego kodu w uruchamianym zadaniu, sprawdzając, czy jest to pierwszy poniedziałek miesiąca w skrypcie, a następnie wywołując go w każdy poniedziałek w crontab. Jest to skrypt rubinowy, więc łatwo jest przetestować dzień tygodnia. Ale miałem nadzieję, że będzie tylko crontab.
Max Williams
1

W systemie Solaris 10 musiałem sformatować warunek w następujący sposób:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"
Wola
źródło
1

Możesz spróbować uruchomić cronjob przez pierwsze siedem dni miesiąca i pozwolić mu działać tylko w poniedziałek.

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

Powyżej powinno dla ciebie pracować.

prostsze
źródło
Daj +1 więcej sukcesów, a następnie uruchom przez pierwszy tydzień i sprawdź na poniedziałek. :-)
xmedeko
1

Polecam użyć

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

zamiast

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

aby uniknąć problemu z lokalizacją.

Manus Freedom
źródło
0

Zrobiłem ogólne rozwiązanie dla tego rodzaju problemów, działa na pierwszy, drugi, trzeci ..... ostatni dzień tygodnia miesiąca.

Możesz użyć tego w następujący sposób:

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"

Skrypt uruchom dzisiaj, jeśli sprawdza zarówno dzień tygodnia, jak i żądany zakres dat tygodnia, jeśli oba pasują, to zwraca 0, w przeciwnym razie 1.

Sprawdź kod tutaj. https://github.com/xr09/cron-last-sunday

MGP
źródło
0

Wierzę, że to rozwiązuje problem bardziej elegancko:

30 8 1-7 * 1 /run/your/job.sh
symcbean
źródło
1
Doh! : „Jeśli oba pola są ograniczone (tzn. Nie są *), polecenie zostanie uruchomione, gdy jedno z pól będzie zgodne z bieżącą godziną.”
symcbean
Również w lutym (tym, który kończy się 28.) nie będzie on uruchamiany co 4 lata.
igraczech
„albo” oznacza którekolwiek z nich, a nie „oba”. będzie to działać codziennie przez pierwsze 7 dni miesiąca.
minusf
Ten wiersz uruchamia polecenie od pierwszego do siódmego każdego miesiąca, a także w każdy poniedziałek
Tomasz Jakub Rup,
0

Ponieważ interpretuję moje instrukcje cron przy użyciu php i js, nie mogę używać bash. W końcu stwierdziłem, że jest to możliwe tylko z cronem:

0 30 8 * 1/1 MON#1

Mam nadzieję, że to pomaga komuś innemu. Niezależnie od tego życzę wszystkim pięknego dnia. :-)

kramer65
źródło
To nie jest cron, prawdopodobnie kwarc
sivann
-1
0 9 1-7 * 1 * 

Będzie to działać w każdy poniedziałek każdego miesiąca.

SIBHI S.
źródło
Odpowiedź została zaakceptowana, czy Twoja odpowiedź jest lepsza, inna lub przydatna w nowszej wersji itp.
mic84