2008-11-28 13 views

Respuesta

45

Si se trata de un proceso que espera ser "suyo" (por ejemplo, está utilizando esto para validar un pid para un proceso que controla), puede simplemente enviarle sig 0.

>> Process.kill 0, 370 
=> 1 
>> Process.kill 0, 2 
Errno::ESRCH: No such process 
    from (irb):5:in `kill' 
    from (irb):5 
>> 
+0

¡Un interesante enfoque! Voy a investigar esto. – Pistos

+3

Dang, pásame. Vi las "nuevas respuestas se han publicado" cosa y mi corazón se hundió :( –

+0

Pero ¿cuál es la señal 0? Anoop? – Pistos

4

Usted puede intentar usar

Process::kill 0, pid 

donde pid es el número PID, si el PID está ejecutando debe devolver 1.

45

@ John T, @Dustin: En realidad, chicos, Analicé el Proceso rdocs, y se ve como

Process.getpgid(pid) 

es un medio menos violento de aplicar la misma técnica.

+0

Encontré que esto puede devolver falsos positivos (informa que se ejecuta cuando en realidad no fue así) en el último Ubuntu. No sé por qué pero en este hilo solo la solución de @balu pareció funcionar para mí. – iain

+0

Supongo que esta no es una solución multiplataforma. (No funciona en Windows, ¿verdad?) – Ajedi32

+3

Creo que la implicación aquí es que 'kill 0' es 'violento' - esto es un error. Los documentos dicen: "Si sig es 0, entonces no se envía ninguna señal, pero todavía se realiza la comprobación de errores, esto se puede utilizar para verificar la existencia de una ID de proceso o ID de grupo de proceso". – Ray

54

La diferencia entre los enfoques Process.getpgid y Process::kill parece ser lo que sucede cuando el pid existe pero es propiedad de otro usuario. Process.getpgid devolverá una respuesta, Process::kill lanzará una excepción (Errno::EPERM).

Basado en eso, recomiendo Process.getpgid, solo por el hecho de que le evita tener que atrapar dos excepciones diferentes.

Aquí está el código que utilizo:

begin 
    Process.getpgid(pid) 
    true 
rescue Errno::ESRCH 
    false 
end 
+0

¿Cómo elimino un proceso propiedad de otro usuario? – Luccas

+1

oneliner: '(Process.getpgid (pid) rescue nil) .present?' –

24

Para los procesos secundarios, otras soluciones como el envío de una señal no se comportará como se espera: van a indicar que el proceso todavía está en marcha, cuando en realidad se cierra.

Puede usar Process.waitpid si desea verificar un proceso que generó usted mismo. La llamada no se bloqueará si está utilizando el indicador Process::WNOHANG y nil se devolverá siempre que el proceso hijo no haya finalizado.

Ejemplo:

pid = Process.spawn('sleep 5') 
Process.waitpid(pid, Process::WNOHANG) # => nil 
sleep 5 
Process.waitpid(pid, Process::WNOHANG) # => pid 

Si el PID no pertenece a un proceso hijo, se lanzará una excepción (Errno::ECHILD: No child processes).

Lo mismo se aplica al Process.waitpid2.

+2

Encontré que esto es más confiable que las soluciones mencionadas anteriormente. ¡Gracias! – iain

+1

Gracias, esa es la respuesta más confiable para procesos engendrados. Para procesos no generados por nosotros, las otras soluciones están bien. – akostadinov

+0

Esta parece ser la única respuesta que funciona en Windows, al menos para mí: D – DarkWiiPlayer

0

A *nix -sólo un acercamiento sería pagar hasta ps y comprobar si existe un delimitador \n (nueva línea) en la cadena devuelta.

Ejemplo IRB salida

1.9.3p448 :067 > `ps -p 56718`               
" PID TTY   TIME CMD\n56718 ttys007 0:03.38 zeus slave: default_bundle \n" 

Empaquetado como un método

def process?(pid) 
    !!`ps -p #{pid.to_i}`["\n"] 
end 
4

En Linux se puede obtener una gran cantidad de atributos de funcionamiento Programm utilizando el sistema de archivos proc:

File.read("/proc/#{pid}/cmdline") 
File.read("/proc/#{pid}/comm") 
0

He tratado este problema antes y ayer lo compilé en la gema "process_exists".

Envía la señal nula (0) al proceso con el pid dado para verificar si existe. Funciona incluso si el usuario actual no tiene permisos para enviar la señal al proceso de recepción.

Uso:

require 'process_exists' 

pid = 12 
pid_exists = Process.exists?(pid) 
4

Ésta es la forma en que he estado haciendo:

def alive?(pid) 
    !!Process.kill(0, pid) rescue false 
end 
+0

No sabía que se puede rescatar así de genial – redcodefinal

+0

Por lo general, no siempre querrás usar 'rescue' así, pero parece justificable aquí. –

-3

Esto funcionó para mí cuando yo era si una canción se está reproduciendo en un código Ruby

def process_running?(pid) 
    return true if pid 
    false 
end 

def play_song_for_real 
    @process_id = fork { exec 'afplay', $song_path } 
end 

si marca process_running(@process_id) obtendrá verdadero si el proceso se está ejecutando o es falso si no es

+0

Esto no funcionará. Por ejemplo, si pongo 'process_running? (1)' producirá 'true' porque' 1' no es 'nil' o' false'. – redcodefinal

+0

Funcionó porque había inicializado pid al process_id. como este 'def play_song_for_real @process_id = fork {exec 'afplay', $ song_path} end' El método' process_running? ', simplemente comprueba si el proceso se está ejecutando y paso el' @ process_id'. Nuevamente, corríjame si me equivoco, quizás funcionó porque tuve suerte (^^) – Hanmaslah

+0

Deberías asegurarte de explicar que en tu ejemplo, mirarlo sin ese conocimiento podría causar malentendidos. La forma en que la mayoría de nosotros esperaría que funcione es tomar un pid entero, no un objeto pid. – redcodefinal

Cuestiones relacionadas