Minutiös cron, nur eine einzige Instanz

9

Gibt es eine Möglichkeit, ein Skript jede Minute (oder 2 oder 5 usw.) auszuführen, aber nur, wenn es noch nicht ausgeführt wird?

Wir haben eine Reihe von Skripten, die jede Minute ausgeführt werden müssen. Manchmal beginnen und enden sie in einer Sekunde, manchmal dauern sie 5 Minuten.

Unsere derzeitige Methode zur Vermeidung gleichzeitiger Ausführungen besteht darin, is_runningin jedem Skript ein Flag zu setzen und zu beenden, wenn es noch aktiviert ist. Dies ist jedoch etwas unzuverlässig (dh schwerwiegende Fehler würden dazu führen, dass das Flag auch nach dem Anhalten des Skripts aktiviert bleibt).

Wir könnten unseren eigenen kleinen Manager schreiben, aber ich frage mich, ob es bereits eine modischere Lösung gibt.

chroder
quelle
+1 Das interessiert mich auch. Ich kenne die Antwort nicht, bin aber an den möglichen Lösungen interessiert.
Saif Bechan
Ein winziger Cron riecht viel nach "mach mich zu einem Dämon"
AD7six

Antworten:

8

Ein besserer Weg ist die Verwendung flockanstelle einer PID-Datei. Überprüfen Sie die Manpage: Herde (1) . Der Vorteil ist, dass unabhängig davon, wie ein Prozess beendet wird / stirbt, die Sperre damit weg ist.

Javier
quelle
3

Ich würde Warners Antwort auf die PID-Datei eher zustimmen. Erreicht die folgende Funktion von Anacron dies jedoch?

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

Ich habe es nicht selbst getestet, ich finde die Dokumentation von anacron nicht gründlich genug ...

Wenn Sie besonders faul sein möchten ;-) Sie können das Skript einfach beenden, wenn das Durchsuchen der ps-Ausgabe den Prozess als ausgeführt zurückgibt. Am besten ist jedoch eine Lock / Pid-Datei.

Kyle Brandt
quelle
Anacron ist eine neuere Version von Cron und bietet daher mehr Funktionen als der alte Standard. Über das 'Wie' wird wahrscheinlich ein SIGCHLD-Handler registriert, der ausgelöst wird, wenn ein untergeordneter Prozess stirbt. Auf diese Weise kann es den Überblick über laufende Kinder behalten und diese Jobs einfach überspringen.
Javier
@ Javier: Ich bin nicht einverstanden mit "Anacron ist eine neuere Version von Cron, daher hat es mehr Funktionen als der alte Standard." Es gibt einige Überschneidungen zwischen Was anacronund cronTun, aber sie lösen unterschiedliche Probleme. Verwendung cron, wie würden Sie einen Job starten , die verpasst wurde , weil eine Maschine war nach unten? Verwendung anacron, wie würden Sie am 25. Dezember oder alle 5 Minuten einen Job starten? (Sie können natürlich Skriptumgehungen durchführen, aber darüber spreche ich nicht.)
Bis auf weiteres angehalten.
@Kyle: Diese Option bewirkt, dass verschiedene Jobs, die gleichzeitig ausgeführt werden sollen, einzeln ausgeführt werden. Es könnte für die Bedürfnisse des OP funktionieren, aber es würde andere Jobs blockieren oder andere Jobs würden es blockieren. Läuft anacronauch nicht in kürzeren Zeiträumen als einem Tag.
Bis auf weiteres angehalten.
@ Tennis Williamson: Ich denke du hast recht, ich habe die Details der Geschichte nicht überprüft. Aber ich denke trotzdem, Sie werden mir zustimmen, dass das Anacron-Projekt nach der Gründung von cron begonnen hat und davon inspiriert ist. Daher ist es nicht verwunderlich, dass es Funktionen hat, die Cron nicht hat. Auch die ursprüngliche Frage war über Cron
Javier
1

Das ist die richtige Lösung für diesen Ansatz. In der Regel wird eine PID-Datei verwendet und ein PID-Test für den Prozess durchgeführt, um sicherzustellen, dass er ausgeführt wird. Im veralteten Zustand würde die Sperrdatei entfernt und der Prozess trotzdem ausgeführt.

Jede zusätzliche Intelligenz wird normalerweise als Daemon in die Software selbst geschrieben, anstatt in cron ausgeführt zu werden.

Warner
quelle
1

Wenn Ihre Skripte in einer Sprache codiert sind, die den Syscall flock (2) unterstützt, können Sie auch eine Sperrdatei mit einem Funktionsaufruf flock (). Beispiel:

Wenn Sie mit Bash oder einer anderen Skriptsprache nicht weiterkommen, die dies nicht unterstützt, ist die bereits vorgeschlagene Lösung mit flock (1) ebenfalls in Ordnung.

PS In jedem Fall sollten Sie eine separate Sperrdatei nur einmal erstellen (falls noch nicht vorhanden) und niemals löschen. Das Verzeichnis "/ var / lock" ist ein guter Ort für solche Dateien.

Famzah
quelle
0

Dies ist eine Lösung, wenn Ihr Skript in Python ausgeführt wird (oder Sie einen Python-Befehl erstellen können, der vor dem nächsten Befehl ausgeführt wird). Ich bin letzte Woche auf genau dieses Problem gestoßen, und obwohl ich einige gute Lösungen gefunden habe, habe ich beschlossen, eine sehr zu erstellen einfaches und sauberes Python-Paket und hochgeladen auf PyPI. Sie könnten sicher sperren, __file__um nicht daran denken zu müssen, ihm einen benutzerdefinierten Ressourcennamen zum Sperren zu geben.

Installieren mit: pip install quicklock

Die Verwendung ist sehr einfach:

[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'!

Schauen Sie sich das an: https://pypi.python.org/pypi/quicklock

Nate Ferrero
quelle