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.
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
>>
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
@ 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.
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 .
Voici comment je le fais:
def alive?(pid)
!!Process.kill(0, pid) rescue false
end
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")
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.
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
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)