Как я могу проверить в Ruby, запущен ли процесс с определенным pid?

Если существует более одного способа, перечислите их. Я знаю только об одном, но мне интересно, есть ли более чистый способ на Ruby.

Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Пошаговое руководство по созданию собственного Slackbot: От установки до развертывания
Шаг 1: Создание приложения Slack Чтобы создать Slackbot, вам необходимо создать приложение Slack. Войдите в свою учетную запись Slack и перейдите на...
48
0
33 077
9
Перейти к ответу Данный вопрос помечен как решенный

Ответы 9

Ответ принят как подходящий

Если это процесс, которым вы ожидаете «владеть» (например, вы используете его для проверки pid для процесса, которым вы управляете), вы можете просто отправить ему sig 0.

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

Интересный подход! Я исследую это.

Pistos 28.11.2008 08:19

блин, опереди меня. Я увидел, что «отправлены новые ответы», и у меня упало сердце :(

John T 28.11.2008 08:21

Но что такое сигнал 0? Нет?

Pistos 28.11.2008 08:27

На моей странице руководства: значение 0, однако, вызовет проверку ошибок (без отправки сигнала). Это можно использовать для проверки действительности pid.

Dustin 28.11.2008 08:35

Черт возьми, смотрел страницу руководства по сигналам и т. д. Не подумал заглянуть на страницу руководства kill. :) Спасибо, Дастин.

Pistos 28.11.2008 08:37

к сожалению, это также возвращает 1, если процесс находится в состоянии «зомби», поэтому не сообщает вам, мертв ли ​​процесс, а только о том, существует ли процесс с этим PID где-то в системе (например, если у вас есть открытый поток для процесс, это вернет 1, даже если процесс завершился). Также обратите внимание, что PID могут повторно использоваться ОС ...

rogerdpack 28.09.2012 12:35

Вы можете попробовать использовать

Process::kill 0, pid

где pid - это номер pid, если pid запущен, он должен вернуть 1.

@John T, @Dustin: На самом деле, ребята, я просмотрел rdocs процесса, и похоже,

Process.getpgid( pid )

менее жестокий способ применения той же техники.

Я обнаружил, что это может возвращать ложные срабатывания (он сообщает о работе, хотя на самом деле это не так) в последней версии Ubuntu. Не знаю почему, но в этой теме мне показалось, что работает только решение от @balu.

iain 13.06.2013 17:46

Я предполагаю, что это не кроссплатформенное решение. (Это не работает в Windows, правда?)

Ajedi32 14.08.2013 17:57

Я думаю, здесь подразумевается, что kill 0 «жестокий» - это ошибка. В документации говорится: «Если sig равен 0, то сигнал не отправляется, но проверка ошибок по-прежнему выполняется; это можно использовать для проверки наличия идентификатора процесса или идентификатора группы процессов».

Ray 09.01.2015 03:32

Получение NotImplementedError (getpgid() function is unimplemented on this machine) на машине Windows. любая помощь?

Manivannan Jeganathan 25.01.2016 17:56

@ManivannanJeganathan Это не работает в Windows. Вместо этого используйте другое решение. (Может быть, Вот этот).

Ajedi32 12.07.2016 22:03

Разница между подходами Process.getpgid и Process::kill, похоже, заключается в том, что происходит, когда pid существует, но принадлежит другому пользователю. Process.getpgid вернет ответ, Process::kill выдаст исключение (Errno::EPERM).

Исходя из этого, я рекомендую Process.getpgid, хотя бы по той причине, что он избавляет вас от необходимости перехватывать два разных исключения.

Вот код, который я использую:

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

Как убить процесс, принадлежащий другому пользователю?

Luccas 01.04.2015 08:58

лайнер: (Process.getpgid(pid) rescue nil).present?

Lev Lukomsky 25.11.2015 16:00

Для дочерних процессов другие решения, такие как отправка сигнала, не будут вести себя должным образом: они укажут, что процесс все еще запущен, когда он фактически завершился.

Вы можете использовать Process.waitpid, если хотите проверить процесс, который вы создали сами. Вызов не будет заблокирован, если вы используете флаг Process::WNOHANG, и nil будет возвращен, пока дочерний процесс не завершился.

Пример:

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

Если pid не принадлежит дочернему процессу, будет сгенерировано исключение (Errno::ECHILD: No child processes).

То же самое относится к Process.waitpid2.

Я обнаружил, что это более надежно, чем вышеупомянутые решения. Спасибо!

iain 13.06.2013 17:32

Спасибо, это самый надежный ответ для порожденных процессов. Для не порожденных нами процессов подойдут и другие решения.

akostadinov 16.04.2015 00:51

Кажется, это единственный ответ, который работает с окнами, по крайней мере, для меня: D

DarkWiiPlayer 19.10.2017 17:25

Подход, использующий только *nix, заключался бы в том, чтобы выполнить оболочку ps и проверить, существует ли в возвращаемой строке разделитель \n (новая строка).

Пример вывода IRB

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

Упаковано как метод

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

В Linux вы можете получить множество атрибутов запущенной программы, используя файловую систему proc:

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

Я имел дело с этой проблемой раньше, а вчера я скомпилировал ее в гем "process_exists".

Он отправляет нулевой сигнал (0) процессу с заданным pid, чтобы проверить, существует ли он. Он работает, даже если у текущего пользователя нет разрешений на отправку сигнала принимающему процессу.

Использование:

require 'process_exists'

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

Вот как я это делал:

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

Обычно вы никогда не захотите использовать rescue таким образом, но здесь это кажется оправданным.

Adam Lassek 07.04.2017 00:52

Другие вопросы по теме