Uruchom skrypt za pośrednictwem crona co drugi tydzień

12

Przeprowadziłem sporo badań, jak to zrobić, i widzę, że nie ma bezpośredniego sposobu, aby uruchomić cron, powiedzmy, co drugi czwartek.

W tej chwili skłaniam się ku stworzeniu skryptu, który będzie uruchamiany co tydzień i dotknie pliku „flag” po uruchomieniu, a jeśli uruchomi się, a plik już tam jest, aby go usunąć (i nie wykonać działania dwutygodniowe).

Moje pytanie brzmi: czy istnieje inny bardziej elegancki lub prostszy sposób na osiągnięcie tego celu, polegającego na tym, że skrypt bash działa automatycznie co drugi tydzień?

Dzięki!

dmkmills
źródło
1
Zamiast pliku flagi można użyć numerów tygodni ISO. (Np.% Strftime.)
@Roger: Zakładam, że masz na myśli warunek w skrypcie.
Wstrzymano do odwołania.
@Dennis: Nie musi tak być (np. Zobaczyć, jak moja odpowiedź sprawdza się poza skryptem), ale moim głównym celem jest to, że byłoby o wiele prostsze i nie wymagałoby żadnego stanu w systemie plików. Uświadomiłem sobie jednak, że ma podobną wadę jak sprawdzanie dnia miesiąca: niektóre lata mają 53 tygodnie, a niektóre 52.

Odpowiedzi:

11
0 0 * * Thu bash -c '(($(date +\%s) / 86400 \% 14))' && your-script

Użyłem bash, aby wykonać matematykę, ponieważ jestem leniwy; zmień to na cokolwiek chcesz. Korzystam z tego, że 1 stycznia 1970 r. Jest czwartkiem; w pozostałe dni tygodnia musisz zastosować przesunięcie. Cron potrzebuje znaków procentu, które uciekły.

Szybkie sprawdzenie:

function check {
  when=$(date --date="$1 $(($RANDOM % 24)):$(($RANDOM % 60))" --utc)
  echo -n "$when: "
  (($(date +%s --date="$when") / 86400 % 14)) && echo run || echo skip
}

for start in "2010-12-02" "2011-12-01"; do
  for x in $(seq 0 12); do
    check "$start + $(($x * 7)) days"
  done
  echo
done

Uwaga: Wybrałem losowe czasy, aby pokazać, że to zadziała, jeśli będzie uruchamiane w dowolnym momencie w czwartek, i wybrałem daty, które przekraczają granice roku, a także obejmują miesiące z 4 i 5 czwartkami.

Wynik:

Thu Dec  2 06:19:00 UTC 2010: run
Thu Dec  9 23:04:00 UTC 2010: skip
Thu Dec 16 05:37:00 UTC 2010: run
Thu Dec 23 12:49:00 UTC 2010: skip
Thu Dec 30 03:59:00 UTC 2010: run
Thu Jan  6 11:29:00 UTC 2011: skip
Thu Jan 13 13:23:00 UTC 2011: run
Thu Jan 20 20:33:00 UTC 2011: skip
Thu Jan 27 16:48:00 UTC 2011: run
Thu Feb  3 17:43:00 UTC 2011: skip
Thu Feb 10 05:49:00 UTC 2011: run
Thu Feb 17 08:46:00 UTC 2011: skip
Thu Feb 24 06:50:00 UTC 2011: run

Thu Dec  1 21:40:00 UTC 2011: run
Thu Dec  8 23:24:00 UTC 2011: skip
Thu Dec 15 22:27:00 UTC 2011: run
Thu Dec 22 02:47:00 UTC 2011: skip
Thu Dec 29 12:44:00 UTC 2011: run
Thu Jan  5 17:59:00 UTC 2012: skip
Thu Jan 12 18:31:00 UTC 2012: run
Thu Jan 19 04:51:00 UTC 2012: skip
Thu Jan 26 08:02:00 UTC 2012: run
Thu Feb  2 17:37:00 UTC 2012: skip
Thu Feb  9 14:08:00 UTC 2012: run
Thu Feb 16 18:50:00 UTC 2012: skip
Thu Feb 23 15:52:00 UTC 2012: run

źródło
2
Sekundy od epoki są z natury w UTC, podczas gdy cron działa w czasie lokalnym. Jeśli strefa czasowa systemu nie jest zgodna z UTC, doprowadzi to do zamieszania. („Dlaczego nie działa? Och, już jest piątek w UTC”). Istnienie czasu letniego sprawia, że ​​obejście tego jest znacznie trudniejsze (choć nie niemożliwe, ponieważ data cal mówi ci o aktualnym przesunięciu UTC)
derobert
5

Jednym ze sposobów może być użycie atnarzędzia, jeśli używasz Linuksa. Możesz umieścić to na końcu skryptu:

at X + 2 weeks -f myscript

gdzie X to czas, w którym chcesz uruchomić skrypt. Aby zainicjować, po prostu zadzwoń atpo raz pierwszy, a następnie powyższa instrukcja będzie odnawiać zaplanowane połączenie.

gvkv
źródło
Jeśli będzie to rozwiązanie długoterminowe, nie polecałbym uruchamiania tego w. Stworzyłbym funkcję w skrypcie, która sprawdziłaby, czy trzeba ją uruchomić
Paul
3

Jeśli możesz używać anacronw systemie, wszystko będzie znacznie prostsze. Aby go użyć anacron, musisz go zainstalować, a także mieć dostęp do konta root. Nie działa na starszych systemach (tj. RHEL 5.x), starsze wersje ancron działają TYLKO podczas uruchamiania. Działa z nowszymi systemami (tj. RHEL 6.x).

Za pomocą anacronmożna zaplanować zadania w bardziej elastyczny sposób, np. Uruchamiać zadanie X raz w tygodniu. anacronUruchamia również zadania, gdy komputer staje się dostępny, tzn. Nie musisz brać pod uwagę, kiedy system jest w górę lub w dół.

Aby uruchomić skrypt co drugi tydzień, musisz dodać wiersz podobny do następującego w pliku / etc / anacrontab:

14 5 myScript script.sh

Szczegółowe informacje znajdują się na stronie podręcznika użytkownika.

memin
źródło
Korzystanie anacronjest zdecydowanie najczystszym rozwiązaniem IMO (chyba że ma pewne niepożądane konsekwencje dla niektórych osób).
JanC
0

Nie jestem pewien, czy istnieje bardziej elegancki sposób definiowania co drugi tydzień, ale może się to przydać.

00 06 1-7,15-21 * * test `date +\%a` = Thu && /path/to/script

Spowoduje to uruchomienie skryptu o godzinie 6:00 w pierwszy i trzeci czwartek miesiąca.

zdenerwować
źródło
2
To by skończyło się na pominięciu tygodnia, jeśli jest miesiąc z 3 czwartkami.
David Z
1
Czy jest miesiąc, który ma tylko 3 czwartki? Chociaż widzę, że przeskakuje o tydzień, jeśli jest 5 czwartków. Można go zaktualizować do 1-7,15-21,29-31, ale wtedy
biegałby jeden po drugim,
1
Czy przez 3 czwartki miałeś na myśli 3 czwartki, w których skrypt będzie działał, a nie 3 całkowite czwartki? Być może po raz pierwszy źle to odczytałem.
pferate
0

Uruchamiam go co tydzień i sprawdzam, czy skrypt ma numer nieparzysty: jeśli tak, wyjdź.

Będzie to wymagało więcej przemyśleń od grudnia do stycznia.

Być może skrypt ustawił plik flagi „ostatnie pomyślne uruchomienie”. Po uruchomieniu skryptu sprawdź, czy plik flagi został ostatnio zmodyfikowany 14 dni temu.

Glenn Jackman
źródło