Drobno cron, zapewniający tylko jedną instancję

9

Czy istnieje sposób uruchamiania skryptu co minutę (lub 2, 5 itd.), Ale tylko wtedy, gdy jeszcze nie jest uruchomiony?

Mamy zestaw skryptów, które muszą być uruchamiane co minutę. Czasami mogą zacząć i zakończyć za sekundę, innym razem mogą trwać 5 minut.

Nasz obecny sposób na unikanie jednoczesnych wykonywania polega na ustawieniu is_runningflagi w każdym skrypcie i wyjściu z niego, jeśli nadal jest włączony. Jest to jednak trochę zawodna (tzn. Błędy krytyczne spowodowałyby, że flaga pozostała włączona nawet po zatrzymaniu skryptu).

Moglibyśmy napisać własnego małego menedżera, ale zastanawiam się, czy istnieje bardziej modne rozwiązanie, które już istnieje.

chroder
źródło
+1 Też mnie to interesuje. Nie znam odpowiedzi, ale interesują mnie możliwe rozwiązania.
Saif Bechan
Drobno cron pachnie „zrób mi demona”
AD7six

Odpowiedzi:

9

lepszym sposobem jest użycie flockzamiast pliku pid. sprawdź stronę: flock (1) . Zaletą jest to, że bez względu na to, jak proces się zakończy / umrze, zamek zniknie wraz z nim.

Javier
źródło
3

Zwykle zgadzam się z odpowiedzią na plik pid Warnera. Jednak czy spełnia to następująca funkcja Anacron?

-s
    Serialize execution of jobs. Anacron will not start a new job before the previous one finished. 

Sam tego nie testowałem, dokumentacja anakrona nie jest wystarczająco dokładna ...

Jeśli chcesz być wyjątkowo leniwy ;-) Możesz po prostu wyjść ze skryptu, jeśli greping przez wyjście ps zwróci proces jako uruchomiony. Ale plik blokady / pid jest najlepszy.

Kyle Brandt
źródło
anacron jest nowszą wersją crona, więc ma więcej funkcji niż stary standard. jeśli chodzi o „how”, prawdopodobnie rejestruje on moduł obsługi SIGCHLD, który jest uruchamiany, gdy umiera proces potomny. dzięki temu może śledzić bieganie dzieci i po prostu pomijać te zadania.
Javier,
@ Javier: Nie zgadzam się z „anacron jest nowszą wersją crona, więc ma więcej funkcji niż stary standard”. Między tym, co anacroni co cronrobią, nakładają się pewne elementy , ale rozwiązują one różne problemy. Używając cron, jak rozpoczniesz pracę, która została pominięta z powodu awarii maszyny? Używając anacron, jak zacząłbyś pracę co 25 grudnia lub co 5 minut? (Możesz oczywiście obejść skrypty, ale nie o tym mówię.)
Wstrzymano do odwołania.
@Kyle: Ta opcja powoduje, że różne zadania zaplanowane do uruchomienia w tym samym czasie będą uruchamiane pojedynczo. Może działać na potrzeby PO, ale blokuje inne zadania lub inne zadania blokują je. Ponadto anacronnie działa w okresach krótszych niż jeden dzień.
Wstrzymano do odwołania.
@Dennis Williamson: Chyba masz rację, nie sprawdziłem szczegółów historii. Ale nadal sądzę, że zgodzisz się, że projekt anacron rozpoczął się po założeniu crona i jest nim zainspirowany; dlatego nie jest zaskakujące, że ma cechy, których nie ma cron. Oryginalne pytanie dotyczyło również crona
Javiera,
1

To właściwe rozwiązanie dla tego podejścia. Zwykle używany byłby plik pid i test pid byłby przeprowadzany względem procesu, aby upewnić się, że jest uruchomiony. Jeśli nieaktualny, plik blokujący zostanie usunięty, a proces i tak zostanie uruchomiony.

Każda dodatkowa inteligencja byłaby zazwyczaj zapisywana w samym oprogramowaniu, jako demon, w przeciwieństwie do uruchamiania w cronie.

Warner
źródło
1

Jeśli twoje skrypty są zakodowane w języku, który obsługuje syscall flock (2), możesz także flock () plik blokady z wywołaniem funkcji. Przykład:

Jeśli utkniesz w Bash lub innym języku skryptowym, który tego nie obsługuje, proponowane rozwiązanie z flock (1) również jest w porządku.

PS W każdym razie oddzielny plik blokady należy utworzyć tylko raz (jeśli jeszcze nie istnieje) i nigdy go nie usuwać. Katalog „/ var / lock” jest dobrym miejscem na takie pliki.

famzah
źródło
0

Jest to rozwiązanie, jeśli twój skrypt działa w Pythonie (lub możesz utworzyć komendę Python, aby działała przed następną komendą) - napotkałem dokładnie ten problem w zeszłym tygodniu i chociaż znalazłem dobre rozwiązania, postanowiłem zrobić bardzo prosty i czysty pakiet Pythona i przesłałem go do PyPI. Z pewnością możesz zablokować, __file__aby nie myśleć o nadaniu mu niestandardowej nazwy zasobu do zablokowania.

Zainstaluj za pomocą: pip install quicklock

Korzystanie z niego jest niezwykle proste:

[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> # Let's create a lock so that only one instance of a script will run
...
>>> singleton('hello world')
>>>
>>> # Let's try to do that again, this should fail
...
>>> singleton('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton
    raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name()))
RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python">
>>>
>>> # But if we quit this process, we release the lock automatically
...
>>> ^D
[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> singleton('hello world')
>>>
>>> # No exception was thrown, we own 'hello world'!

Spójrz: https://pypi.python.org/pypi/quicklock

Nate Ferrero
źródło