Cronograficamente, garantendo solo una singola istanza


9

C'è un modo per eseguire uno script ogni minuto (o 2, o 5, ecc.), Ma solo se non è già in esecuzione?

Abbiamo una serie di script che devono essere eseguiti ogni minuto. A volte potrebbero iniziare e finire in un secondo, altre volte potrebbero andare avanti per 5 minuti.

Il nostro modo attuale di evitare esecuzioni simultanee è impostare un is_runningflag in ogni script ed uscire se è ancora abilitato. Ma questo è un po 'inaffidabile (ad esempio, errori fatali farebbero rimanere abilitato il flag anche dopo l'arresto dello script).

Potremmo scrivere il nostro piccolo manager, ma mi chiedo se esiste già una soluzione più alla moda.


+1 Mi interessa anche questo. Non conosco la risposta, tuttavia sono interessato alle possibili soluzioni.
Saif Bechan,

Risposte:


8

un modo migliore è usare flockinvece di un pidfile. controlla la manpage: flock (1) . Il vantaggio è che, indipendentemente dal modo in cui un processo termina / muore, il blocco è andato con esso.


3

Tenderei ad essere d'accordo con la risposta del file pid di Warner. Tuttavia, la seguente caratteristica di Anacron realizza questo?

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

Non l'ho provato da solo, non trovo la documentazione di Anacron abbastanza approfondita ...

Se vuoi essere particolarmente pigro ;-) Puoi semplicemente uscire dallo script se grepping attraverso l'output ps restituisce il processo in esecuzione. Ma un file lock / pid è il migliore.


anacron è una versione più recente di cron, quindi ha più funzionalità rispetto al vecchio standard. riguardo al "come", probabilmente registra un gestore SIGCHLD, che viene attivato quando un processo figlio muore. così può tenere traccia della corsa dei bambini e semplicemente saltare quei lavori.
Javier,

@ Javier: non sono d'accordo con "anacron è una versione più recente di cron, quindi ha più funzionalità rispetto al vecchio standard". C'è qualche sovrapposizione tra cosa anacrone croncosa, ma risolvono diversi problemi. Usando cron, come inizieresti un lavoro perso perché una macchina era inattiva? Utilizzando anacron, come inizieresti un lavoro ogni 25 dicembre o ogni 5 minuti? (Ovviamente puoi risolvere il problema con la sceneggiatura, ma non è di questo che sto parlando.)
Pausa fino a nuovo avviso.

@Kyle: questa opzione fa sì che diversi lavori pianificati vengano eseguiti contemporaneamente per essere eseguiti uno alla volta. Potrebbe funzionare per le necessità del PO, ma bloccherebbe altri lavori o altri lavori lo bloccherebbe. Inoltre, anacronnon viene eseguito in periodi inferiori a un giorno.
In pausa fino a ulteriore avviso.

@Dennis Williamson: suppongo tu abbia ragione, non ho controllato i dettagli della cronologia. Ma suppongo comunque che accetti che il progetto Anacron è iniziato dopo che cron è stato praticamente istituito e ne è ispirato; quindi non sorprende che abbia caratteristiche che cron non ha. Inoltre, la domanda originale riguardava cron
Javier,

1

Questa è la soluzione corretta per questo approccio. In genere, viene utilizzato un file pid e viene eseguito un test pid sul processo per assicurarsi che sia in esecuzione. Se non aggiornato, il file di blocco verrà rimosso e il processo verrà eseguito comunque.

Qualsiasi ulteriore intelligenza verrebbe tipicamente scritta nel software stesso, come un demone, invece di essere eseguita in cron.


1

Se i tuoi script sono codificati in una lingua che supporta flock (2) syscall, allora potresti flock () un file di blocco con una chiamata di funzione. Esempio:

Se sei bloccato con Bash o altri linguaggi di scripting che non lo supportano, anche la soluzione già proposta con flock (1) va bene.

PS In ogni caso, dovresti creare un file di blocco separato solo una volta (se non esiste già) e non cancellarlo mai. La directory "/ var / lock" è un buon posto per tali file.


0

Questa è una soluzione se il tuo script viene eseguito in Python (o potresti creare un comando Python da eseguire prima del comando successivo) - Ho riscontrato questo esatto problema la scorsa settimana e sebbene abbia trovato delle buone soluzioni, ho deciso di fare un pacchetto python semplice e pulito e caricato su PyPI. Potresti sicuramente bloccare __file__per non dover pensare di assegnargli un nome di risorsa personalizzato da bloccare.

Installa con: pip install quicklock

Usarlo è estremamente semplice:

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

Dai un'occhiata: https://pypi.python.org/pypi/quicklock

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.