Minuto cron, asegurando solo una instancia

9

¿Hay alguna manera de ejecutar un script cada minuto (o 2, o 5, etc.), pero solo si aún no se está ejecutando?

Tenemos un conjunto de scripts que deben ejecutarse cada minuto. A veces pueden comenzar y terminar en un segundo, otras veces pueden continuar durante 5 minutos.

Nuestra forma actual de evitar ejecuciones simultáneas es estableciendo un is_runningindicador en cada script y saliendo si aún está habilitado. Pero esto es poco confiable (es decir, los errores fatales causarían que el indicador permanezca habilitado incluso después de que el script se detenga).

Podríamos escribir nuestro propio pequeño administrador, pero me pregunto si ya existe una solución más moderna.

chroder
fuente
+1 Estoy interesado en esto también. No sé la respuesta, sin embargo, estoy interesado en las posibles soluciones.
Saif Bechan
Un cron minucioso huele mucho a "hazme un demonio"
AD7six

Respuestas:

8

una mejor manera es usar en flocklugar de un archivo pid. verifique la página de manual: flock (1) . La ventaja es que no importa cómo termine / muera un proceso, la cerradura desaparece con él.

Javier
fuente
3

Tendería a estar de acuerdo con la respuesta del archivo pid de Warner. Sin embargo, ¿la siguiente característica de Anacron logra esto?

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

No lo he probado yo mismo, no encuentro la documentación de anacron lo suficientemente completa ...

Si desea ser particularmente perezoso ;-) Puede hacer que la secuencia de comandos salga si greping a través de la salida ps devuelve el proceso como en ejecución. Pero un archivo de bloqueo / pid es lo mejor.

Kyle Brandt
fuente
anacron es una versión más reciente de cron, por lo que tiene más funciones que el estándar anterior. sobre el 'cómo', probablemente registra un controlador SIGCHLD, que se activa cuando un proceso secundario muere. por lo tanto, puede realizar un seguimiento de la ejecución de niños y simplemente omitir esos trabajos.
Javier
@ Javier: No estoy de acuerdo con "anacron es una versión más reciente de cron, por lo que tiene más funciones que el estándar anterior". Existe cierta superposición entre qué anacrony qué cronhacer, pero resuelven diferentes problemas. Utilizando cron, ¿cómo comenzaría un trabajo que se perdió porque una máquina no funcionaba? Utilizando anacron, ¿cómo comenzaría un trabajo cada 25 de diciembre o cada 5 minutos? (Por supuesto, puede solucionar el guión, pero eso no es de lo que estoy hablando).
Pausó hasta nuevo aviso.
@Kyle: esa opción hace que diferentes trabajos programados se ejecuten al mismo tiempo para ejecutarse uno a la vez. Podría funcionar para la necesidad del OP, pero bloquearía otros trabajos u otros trabajos lo bloquearían. Además, anacronno se ejecuta en períodos más cortos que un día.
Pausado hasta nuevo aviso.
@ Dennis Williamson: supongo que tienes razón, no he revisado los detalles del historial. Pero aún así supongo que estará de acuerdo en que el proyecto anacron comenzó después de que cron se estableció más o menos, y está inspirado en él; Por lo tanto, no es sorprendente que tenga características que no tiene cron. Además, la pregunta original era sobre cron
Javier
1

Esa es la solución adecuada para ese enfoque. Normalmente, se usaría un archivo pid y se realizaría una prueba pid contra el proceso para asegurar que se esté ejecutando. Si está obsoleto, el archivo de bloqueo se eliminará y el proceso se ejecutará de todos modos.

Cualquier inteligencia adicional normalmente se escribiría en el propio software, como un demonio, en lugar de ejecutarse en cron.

Warner
fuente
1

Si sus secuencias de comandos están codificadas en un lenguaje que admite la llamada al sistema flock (2), entonces también puede agrupar () un archivo de bloqueo con una llamada a la función. Ejemplo:

Si está atrapado con Bash u otro lenguaje de secuencias de comandos que no lo admite, la solución ya propuesta con flock (1) también está bien.

PD En cualquier caso, debe crear un archivo de bloqueo por separado solo una vez (si aún no existe), y nunca eliminarlo. El directorio "/ var / lock" es un buen lugar para dichos archivos.

famzah
fuente
0

Esta es una solución si su script se ejecuta en python (o podría crear un comando de python para que se ejecute antes del siguiente comando). La semana pasada me topé con este problema exacto, y aunque encontré algunas buenas soluciones, decidí hacer un paquete de python simple y limpio y lo subió a PyPI. Ciertamente podría bloquear __file__para no tener que pensar en darle un nombre de recurso personalizado para bloquear.

Instalar con: pip install quicklock

Usarlo es extremadamente simple:

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

Echa un vistazo: https://pypi.python.org/pypi/quicklock

Nate Ferrero
fuente