2012-03-12 12 views
10

En Ruby 1.9.x, ¿cuál podría ser una forma sencilla de no permitir que mi script Ruby vuelva a ejecutarse o esperar a que termine la instancia anterior? **¿Cómo limitar las instancias simultáneas del mismo script de Ruby?

Espero evitar el bloqueo de archivos desordenado o verificar la tabla de procesos.

¿Hay algo así como un global mutex o un semáforo ya en el núcleo? Estudié el Mutex nativo, pero eso solo parece aplicarse a los hilos dentro de un proceso Ruby, no a través de procesos diferentes.

** Más adelante, podría agregar la funcionalidad de tiempo de espera, o limitar a N instancias, o utilizar más de un bloqueo global (uno por recurso de todo el sistema que solo debería tener una instancia máxima).

Respuesta

2

Esto generalmente se resuelve en el nivel del sistema operativo, al buscar un archivo de marca y no intentar iniciar de nuevo, no en el script en sí.

Pero, si desea verificar la secuencia de comandos, busque un archivo de semáforo en una ubicación conocida. Si existe y no está dentro de una ventana de tiempo determinada que cabe en su ventana de inicio, elimine el archivo y cree uno nuevo. Si está en su ventana de tiempo, salga.

Puede usar el bloqueo de archivos o almacenar marcas de tiempo en el archivo o muchas otras comprobaciones si no se inicia utilizando un mecanismo de tipo cron. Cada enfoque tiene sus ventajas y desventajas.

Tendrá que atrapar interrupciones para que cuando salga de un Control-C también borre ese archivo.

Lea las preguntas relacionadas a la derecha. Aunque están cubriendo varios otros idiomas, las respuestas sugeridas ayudarán a comprender los problemas y las posibles formas de evitarlos en todos los idiomas.

+0

Ya envuelvo la mayoría de mis scripts de Ruby con Bash que ellos mismos usan código como '[-z" $ (pidof -x -o% PPID -o $$ $ {0 ## * /}) "] || exec echo "$ (date) $ 0: $$ ya huele a PID: $ (pidof -x $ 0), ¡adiós!" 'sin embargo, eso sirve para otros propósitos. Una solución aún mejor que ya está contenida dentro de Ruby es bloquear cualquier archivo fijo para escribir, por ejemplo. '/ tmp/scriptname.rb.lock'. Al salir o incluso si mi código falla (lo cual a menudo genera excepciones), el sistema borrará ese bloqueo. Voy a seguir con ese truco hasta que haya una interfaz limpia y nativa para los semáforos globales, que de todos modos necesitaré. – Marcos

5

Este código muy corto se congelará en su lugar hasta que un fichero de bloqueo en/tmp llamado así por su guión está bloqueado exclusivamente:

File.open("/tmp/#{File.basename $0}.lock", File::RDWR|File::CREAT, 0644).flock(File::LOCK_EX) 

cualquier otro programa de bloqueo que, Ruby o no, sólo necesita terminar o ser matado , para que la instancia de proceso más nueva se desbloquee y continúe. Así que, por ahora, esta solución alternativa hace lo que necesito. Puedo llamar a mi programa de rubí con

timeout 1m ./myrubyscript.rb 

de la fiesta de envolver script si me impaciento, por ejemplo. (En ese ejemplo, myrubyscript.rb terminará después de 1 minuto ya sea que tenga o no su bloqueo de archivo para continuar haciendo lo que estaba escrito.)

Cuestiones relacionadas