2010-01-02 12 views
7

estoy tratando de configurar un servidor para las pruebas de integración (especificaciones en realidad) a través de ruby ​​y no sé cómo controlar el proceso.cómo controlar (iniciar/matar) un proceso en segundo plano (aplicación de servidor) en ruby ​​

es así, lo que estoy tratando de hacer es:

  1. ejecutar una tarea de rastrillo para mi joya que ejecuta las especificaciones de integración
  2. la tarea tiene que empezar primero un servidor (yo uso WEBrick) y a continuación, ejecutar las especificaciones
  3. después de ejecutar las especificaciones que debe matar al WEBrick, así que no me queda algún proceso en segundo plano sin usar

WEBrick no es un requisito, pero está incluido en el rubí libra estándar poder usarlo sería genial.

¡Espero que alguien pueda ayudar!

ps. Me estoy ejecutando en Linux, por lo que tener este trabajo para Windows no es mi principal prioridad (en este momento).

Respuesta

12

La forma estándar es utilizar las funciones del sistema fork (para duplicar el proceso actual), exec (para reemplazar el proceso actual por un archivo ejecutable) y kill (para enviar una señal a un proceso para terminarlo).

Por ejemplo:

pid = fork do 
    # this code is run in the child process 
    # you can do anything here, like changing current directory or reopening STDOUT 
    exec "/path/to/executable" 
end 

# this code is run in the parent process 
# do your stuffs 

# kill it (other signals than TERM may be used, depending on the program you want 
# to kill. The signal KILL will always work but the process won't be allowed 
# to cleanup anything) 
Process.kill "TERM", pid 

# you have to wait for its termination, otherwise it will become a zombie process 
# (or you can use Process.detach) 
Process.wait pid 

Esto debería funcionar en cualquier sistema Unix. Windows crea el proceso de una manera diferente.

+0

genial. muchas gracias. mientras probaba cosas, tuve una "solución" casi idéntica que casi funcionó, pero desafortunadamente no puedo entender dónde era diferente. también necesité agregar un descanso después de hornear el proceso para esperar hasta que el servidor estuviera disponible. ¡Gracias! – rubiii

+0

pude reproducir la diferencia. ejecuté Kernel # system en lugar de Kernel # exec. Kernel # exec "reemplaza el proceso actual ejecutando el comando externo dado" donde Kernel # system "ejecuta el comando en una subshell". – rubiii

+0

¿Puede el proceso secundario mantenerse vivo incluso si sale el script de ruby? –

0

He intentado fork, pero tiene algún tipo de problema cuando ActiveRecord está involucrado en ambos procesos. Sugeriría el complemento Spawn (http://github.com/tra/spawn). Solo tenedor, pero se ocupa de ActiveRecord.

+0

si necesita ar, su solución podría ser el camino a seguir. Así que gracias. pero realmente no necesito usar ar. – rubiii

2

Solo tenía que hacer algo similar y esto es lo que se me ocurrió. La respuesta de @Michael Witrant me ayudó a comenzar, pero cambié algunas cosas, como usar Process.spawn en lugar de fork (newer and better).

# start spawns a process and returns the pid of the process 
def start(exe) 
    puts "Starting #{exe}" 
    pid = spawn(exe) 
    # need to detach to avoid daemon processes: http://www.ruby-doc.org/core-2.1.3/Process.html#method-c-detach 
    Process.detach(pid) 
    return pid 
end 

# This will kill off all the programs we started 
def killall(pids) 
    pids.each do |pid| 
     puts "Killing #{pid}" 
     # kill it (other signals than TERM may be used, depending on the program you want 
     # to kill. The signal KILL will always work but the process won't be allowed 
     # to cleanup anything) 
     begin 
     Process.kill "TERM", pid 

     # you have to wait for its termination, otherwise it will become a zombie process 
     # (or you can use Process.detach) 
     Process.wait pid 
     rescue => ex 
     puts "ERROR: Couldn't kill #{pid}. #{ex.class}=#{ex.message}" 
     end 
    end 
end 

# Now we can start processes and keep the pids for killing them later 
pids = [] 
pids << start('./someprogram') 

# Do whatever you want here, run your tests, etc. 

# When you're done, be sure to kill of the processes you spawned 
killall(pids) 

Eso es todo lo que escribió, pruébalo y cuéntame cómo funciona.

Cuestiones relacionadas