web-dev-qa-db-fra.com

Comment puis-je vérifier auprès de Ruby si un processus avec un certain pid est en cours d'exécution?

S'il y a plus d'une façon, veuillez les énumérer. Je ne connais que l'un d'entre eux, mais je me demande s'il existe une solution plus propre, en mode rubis.

43
Pistos

S'il s'agit d'un processus que vous comptez "posséder" (par exemple, vous l'utilisez pour valider un pid pour un processus que vous contrôlez), vous pouvez simplement lui envoyer le signal 0.

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

La différence entre les approches Process.getpgid et Process::kill semble correspondre à ce qui se produit lorsque le pid existe mais qu’il appartient à un autre utilisateur. Process.getpgid renvoie une réponse, Process::kill lève une exception (Errno::EPERM).

Sur cette base, je recommande Process.getpgid, ne serait-ce que pour la simple raison que cela vous évite d'avoir à intercepter deux exceptions différentes.

Voici le code que j'utilise:

begin
  Process.getpgid( pid )
  true
rescue Errno::ESRCH
  false
end
57
tonystubblebine

@ John T, @Dustin: En fait, les gars, j'ai parcouru les processus du processus, et on dirait 

Process.getpgid( pid )

est un moyen moins violent d'appliquer la même technique.

45
Pistos

Pour les processus enfants, d'autres solutions telles que l'envoi d'un signal ne se comporteront pas comme prévu: elles indiqueront que le processus est toujours en cours d'exécution lorsqu'il s'est arrêté.

Vous pouvez utiliser Process.waitpid si vous voulez vérifier un processus que vous avez créé. L'appel ne sera pas bloqué si vous utilisez l'indicateur Process::WNOHANG et que nil est renvoyé tant que le processus enfant ne s'est pas arrêté.

Exemple:

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

Si le pid n'appartient pas à un processus enfant, une exception sera levée (Errno::ECHILD: No child processes).

La même chose s'applique à Process.waitpid2 .

26
balu

Voici comment je le fais:

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

Sous Linux, vous pouvez obtenir beaucoup d'attributs d'un programme en cours d'exécution à l'aide du système de fichiers proc:

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

Vous pouvez essayer d'utiliser

Process::kill 0, pid

où pid est le nombre pid. Si le pid est en cours d'exécution, il doit renvoyer 1.

4
John T

Une approche *nix- uniquement consisterait à transformer Shell en sortie en ps et à vérifier si un délimiteur \n (nouvelle ligne) existe dans la chaîne renvoyée.

Exemple de sortie IRB

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

Emballé en tant que méthode

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

J'ai déjà traité ce problème et hier, je l'ai compilé dans le " process_exists ". 

Il envoie le signal null (0) au processus avec le pid donné pour vérifier s'il existe. Cela fonctionne même si l'utilisateur actuel n'a pas l'autorisation d'envoyer le signal au processus de réception.

Usage:

require 'process_exists'

pid = 12
pid_exists = Process.exists?(pid)
0
Wilson Silva