Pregunta

Tengo un proceso de ejecución prolongado y lo necesito para iniciar otro proceso (que también se ejecutará durante un buen rato). Solo necesito iniciarlo y luego olvidarlo por completo.

Me las arreglé para hacer lo que necesitaba extrayendo un código del libro Programming Ruby, pero me gustaría encontrar la mejor forma y entender lo que está pasando. Esto es lo que obtuve inicialmente:

exec("whatever --take-very-long") if fork.nil?
Process.detach($)


Entonces, ¿es este el camino, o de qué otra manera debo hacerlo?

Después de revisar las respuestas a continuación, terminé con este código, que parece tener más sentido:

(pid = fork) ? Process.detach(pid) : exec("foo")


Apreciaría alguna explicación sobre cómo funciona fork . [ya tengo eso]

¿Se estaba separando $$ , verdad? No sé por qué esto funciona, y me encantaría tener un mejor conocimiento de la situación.

¿Fue útil?

Solución

La función fork separa tu proceso en dos.

Los procesos

Ambos reciben el resultado de la función. El hijo recibe un valor de cero / nil (y, por lo tanto, sabe que es el hijo) y el padre recibe el PID del hijo.

Por lo tanto:

exec("something") if fork.nil?

hará que el proceso hijo comience " algo " ;, y el proceso padre continuará con el lugar donde estaba.

Tenga en cuenta que exec () reemplaza el proceso actual con " algo " ;, por lo que el proceso hijo nunca ejecutará ningún código Ruby posterior.

La llamada a Process.detach () parece que podría ser incorrecta. Habría esperado que tuviera el PID del niño en él, pero si leo su código correctamente, en realidad está separando el proceso principal.

Otros consejos

Alnitak tiene razón. Aquí hay una forma más explícita de escribirlo, sin $$

pid = Process.fork
if pid.nil? then
  # In child
  exec "whatever --take-very-long"
else
  # In parent
  Process.detach(pid)
end

El propósito de separarse es solo decir, " No me importa cuando el niño termina " para evitar procesos zombie .

Separar $$ no estaba bien. De p. 348 del Pickaxe (2ª ed.):

  

$$ Fixnum El número de proceso del programa que se está ejecutando. [r / o]

Esta sección, " Variables y constantes " en el " Ruby Language " capítulo, es muy útil para decodificar varias constantes de $ ruby ??short - sin embargo, la edición en línea (la primera

Entonces, lo que realmente estaban haciendo era separar el programa de sí mismo, no de su hijo. Como han dicho otros, la manera correcta de separarse del niño es usar el pid del niño devuelto desde fork () .

Las otras respuestas son buenas si está seguro de que desea separar el proceso secundario. Sin embargo, si no le importa o prefiere mantener el proceso secundario adjunto (por ejemplo, está lanzando sub-servidores / servicios para una aplicación web), puede aprovechar la siguiente taquigrafía

fork do
    exec('whatever --option-flag')
end

Proporcionar un bloque le dice a fork que ejecute ese bloque (y solo ese bloque) en el proceso secundario, mientras continúa en el padre.

Encontré que las respuestas anteriores rompieron mi terminal y estropearon la salida. Esta es la solución que encontré.

   system("nohup ./test.sh &")

en caso de que alguien tenga el mismo problema, mi objetivo era iniciar sesión en un servidor ssh y luego mantener el proceso en ejecución indefinidamente. asi que test.sh es esto

#!/usr/bin/expect -f
spawn ssh host -l admin -i cloudkey  
expect "pass"
send "superpass\r"
sleep 1000000
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top