Zaplanowałem uruchamianie zadania cron co minutę, ale czasami skrypt trwa dłużej niż minutę i nie chcę, aby zadania zaczęły się „nakładać” na siebie. Myślę, że jest to problem współbieżności - tzn. Wykonywanie skryptu musi się wykluczać.
Aby rozwiązać problem, sprawiłem, że skrypt szukał określonego pliku („ lockfile.txt ”) i kończy działanie, jeśli istnieje, lub touch
jeśli nie. Ale to kiepski semafor! Czy jest jakaś najlepsza praktyka, o której powinienem wiedzieć? Czy zamiast tego powinienem napisać demona?
źródło
flock -n file command
iflock -n file -c command
?-c
uruchamia określone polecenie przez powłokę (jak na stronie podręcznika), podczas gdy-c
forma „goła” (nie- ) jest tylkoexec
poleceniem podanym . Przekazanie czegoś przez powłokę umożliwia wykonywanie czynności podobnych do powłoki (takich jak uruchamianie wielu poleceń oddzielonych za pomocą;
lub&&
), ale także otwiera cię na ataki rozszerzania powłoki, jeśli używasz niezaufanego wejścia.frequent_cron_job
polecenia, które próbowało pokazać, że jest uruchamiane co minutę. Usunąłem go, ponieważ nie dodał nic użytecznego i spowodował zamieszanie (twoje, jeśli nikt inny nie jest przez lata).Najlepszym sposobem w powłoce jest użycie stada (1)
źródło
99
i>
tak jest99> /...
Właściwie
flock -n
może być użyte zamiastlckdo
*, więc będziesz używać kodu od programistów jądra.Opierając się na przykładzie womble , napiszesz coś takiego:
BTW, patrząc na kod, wszystko
flock
,lockrun
ilckdo
robić dokładnie to samo, więc to tylko kwestia co jest najłatwiej dostępne.źródło
Możesz użyć pliku blokady. Utwórz ten plik po uruchomieniu skryptu i usuń go po zakończeniu. Skrypt, zanim uruchomi swoją główną procedurę, powinien sprawdzić, czy plik blokady istnieje i postępować odpowiednio.
Pliki blokujące są używane przez skrypty startowe oraz wiele innych aplikacji i narzędzi w systemach uniksowych.
źródło
Nie określiłeś, czy chcesz, aby skrypt czekał na zakończenie poprzedniego uruchomienia, czy nie. Poprzez „Nie chcę, aby zadania zaczęły się„ nakładać ”jeden na drugi, myślę, że sugerujesz, że chcesz, aby skrypt został zamknięty, jeśli jest już uruchomiony,
Więc jeśli nie chcesz polegać na lckdo lub podobnym, możesz to zrobić:
źródło
Może to również oznaczać, że robisz coś złego. Jeśli twoje zadania działają tak blisko i tak często, być może powinieneś rozważyć usunięcie ich z programu i uczynienie z niego programu w stylu demona.
źródło
Twój demon cron nie powinien wywoływać zadań, jeśli poprzednie instancje nadal działają. Jestem programistą jednego demona cron dcron i staramy się temu zapobiec. Nie wiem, jak Vixie cron lub inne demony sobie z tym radzą.
źródło
Poleciłbym użycie polecenia run-one - o wiele prostsze niż radzenie sobie z blokadami. Z dokumentów:
run-one to skrypt otoki, który uruchamia nie więcej niż jedno unikalne wystąpienie jakiegoś polecenia z unikalnym zestawem argumentów. Jest to często przydatne w cronjobs, gdy nie chcesz, aby działała więcej niż jedna kopia na raz.
run-this-one jest dokładnie tak samo jak run-one, z tym wyjątkiem, że użyje pgrep i kill do znalezienia i zabicia wszelkich uruchomionych procesów należących do użytkownika i dopasowania poleceń i argumentów docelowych. Zauważ, że run-this-one blokuje się podczas próby zabicia pasujących procesów, dopóki wszystkie pasujące procesy nie zostaną zakończone.
run-one-stale działa dokładnie tak, jak run-one, z tym wyjątkiem, że odradza się „COMMAND [ARGS]” za każdym razem, gdy kończy się polecenie COMMAND (zero lub zero).
keep-one-running to alias do ciągłego uruchamiania.
run-one-dopóki-sukces działa dokładnie tak, jak run-one-stale, z tym wyjątkiem, że odradza się „COMMAND [ARGS]”, dopóki COMMAND nie zakończy się pomyślnie (tzn. zakończy zero).
run-one- till -failure działa dokładnie tak, jak run-one-stale, z tym wyjątkiem, że odradza się „COMMAND [ARGS]”, dopóki COMMAND nie zakończy się niepowodzeniem (tzn. zakończy się niezerowo).
źródło
Teraz, gdy systemd jest już dostępny, istnieje inny mechanizm planowania w systemach Linux:
ZA
systemd.timer
W
/etc/systemd/system/myjob.service
lub~/.config/systemd/user/myjob.service
:W
/etc/systemd/system/myjob.timer
lub~/.config/systemd/user/myjob.timer
:Jeśli jednostka serwisowa już aktywuje się, gdy następny timer zostanie aktywowany, to kolejne wystąpienie usługi nie zostanie uruchomione.
Alternatywa, która uruchamia zadanie raz podczas rozruchu i minutę po zakończeniu każdego uruchomienia:
źródło
Stworzyłem jeden słoik, aby rozwiązać taki problem, jak uruchomione duplikaty cronów, może to być cron java lub shell. Wystarczy podać nazwę crona w Duplicates.CloseSessions („Demo.jar”), aby wyszukać i zabić istniejący pid dla tego crona oprócz bieżącej. Wdrożyłem metodę, aby to zrobić. Zaimek ciągu = ManagementFactory.getRuntimeMXBean (). GetName (); Ciąg pid = proname.split („@”) [0]; System.out.println („Current PID:” + pid);
A następnie zabij killid string ponownie poleceniem powłoki
źródło
Odpowiedź Philipa Reynoldsa rozpocznie wykonywanie kodu po upływie czasu oczekiwania 5 sekund bez uzyskania blokady. Obserwowanie Flocka wydaje się nie działać. Zmodyfikowałem odpowiedź @Philip Reynolds na
aby kod nigdy nie był wykonywany jednocześnie. Zamiast tego po upływie 5 sekund proces zakończy się na 1, jeśli do tego czasu nie uzyska blokady.
źródło