Как проверить, существует ли идентификатор процесса (PID)

В сценарии bash я хочу сделать следующее (в псевдокоде):

if [ a process exists with $PID ]; then kill $PID fi 

Какое подходящее выражение для условного оператора?

Чтобы проверить наличие процесса, используйте

 kill -0 $pid 

Но так же, как @unwind сказал, если вы собираетесь убить его в любом случае, просто

 kill $pid 

или у вас будет состояние гонки.

Если вы хотите игнорировать текстовый вывод kill и делать что-то на основе кода выхода, вы можете

 if ! kill $pid > /dev/null 2>&1; then echo "Could not send SIGTERM to process $pid" >&2 fi 

Лучший способ:

 if ps -p $PID > /dev/null then echo "$PID is running" # Do something knowing the pid exists, ie the process with $PID is running fi 

Проблема с:

 kill -0 $PID 

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

 kill -0 1 

а также

 kill -0 $non-running-pid 

имеют неотличимый (ненулевой) код выхода для обычного пользователя, но процесс инициализации (PID 1), безусловно, работает.

ОБСУЖДЕНИЕ

Ответы, в которых обсуждаются условия убийства и расы, абсолютно правильны, если тело испытания является «убитым». Я искал генерала « как вы тестируете существование PID в bash ».

Метод / proc интересен, но в некотором смысле нарушает дух абстракции команды ps, т. Е. Вам не нужно искать в / proc, потому что если Linus решит называть файл exe чем-то еще?

 if [ -n "$PID" -a -e /proc/$PID ]; then echo "process exists" fi 

или

 if [ -n "$(ps -p $PID -o pid=)" ] 

В последней форме -o pid= – выходной формат для отображения только столбца идентификатора процесса без заголовка. Кавычки необходимы для непустого оператора string -n чтобы дать правильный результат.

Команда ps с -p $PID может сделать это:

 $ ps -p 3531 PID TTY TIME CMD 3531 ? 00:03:07 emacs 

У вас есть два пути:

Давайте начнем с поиска конкретного приложения на моем ноутбуке:

 [[email protected]:~]# ps fax | grep mozilla 3358 ? S 0:00 \_ /bin/sh /usr/lib/firefox-3.5/run-mozilla.sh /usr/lib/firefox-3.5/firefox 16198 pts/2 S+ 0:00 \_ grep mozilla 

Все примеры теперь будут искать PID 3358.

Первый путь : запустите «ps aux» и grep для PID во втором столбце. В этом примере я ищу firefox, а затем для PID:

 [[email protected]:~]# ps aux | awk '{print $2 }' | grep 3358 3358 

Таким образом, ваш код будет:

 if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then kill $PID fi 

Второй способ : просто найдите что-то в каталоге /proc/$PID . В этом примере я использую «exe», но вы можете использовать что-нибудь еще.

 [[email protected]:~]# ls -l /proc/3358/exe lrwxrwxrwx. 1 elcuco elcuco 0 2010-06-15 12:33 /proc/3358/exe -> /bin/bash 

Таким образом, ваш код будет:

 if [ -f /proc/$PID/exe ]; then kill $PID fi 

BTW: что не так с kill -9 $PID || true kill -9 $PID || true ?


РЕДАКТИРОВАТЬ:

Подумав об этом в течение нескольких месяцев .. (около 24 …) оригинальная идея, которую я здесь привела, – это хороший хак, но очень неспособен. Хотя он учит некоторым деталям реализации Linux, он не сможет работать на Mac, Solaris или * BSD. Это может даже потерпеть неудачу в будущих ядрах Linux. Пожалуйста, используйте «ps», как описано в других ответах.

Я думаю, что это плохое решение, которое открывается для условий гонки. Что делать, если процесс умирает между вашим тестом и вашим призывом убивать? Тогда убить не удастся. Так почему бы просто не попробовать убить во всех случаях и проверить его возвращаемое значение, чтобы узнать, как оно прошло?

Кажется, вы хотите

 wait $PID 

который вернется при завершении $pid .

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

 ps -p $PID 

чтобы проверить, жив ли процесс (это более эффективно, чем kill -0 $pid потому что он будет работать, даже если вы не являетесь владельцем pid).

здесь я храню PID в файле с именем .pid (который вроде как / run / …) и выполняет только скрипт, если он еще не выполняется.

 #!/bin/bash if [ -f .pid ]; then read pid < .pid echo $pid ps -p $pid > /dev/null r=$? if [ $r -eq 0 ]; then echo "$pid is currently running, not executing $0 twice, exiting now..." exit 1 fi fi echo $$ > .pid # do things here rm .pid 

Примечание: есть условие гонки, так как оно не проверяет, как называется pid. если система перезагружена, а .pid существует, но используется другим приложением, это может привести к «непредвиденным последствиям».

Например, в GNU / Linux вы можете использовать:

 Pid=$(pidof `process_name`) if [ $Pid > 0 ]; then do something else do something fi 

Или что-то вроде

 Pin=$(ps -A | grep name | awk 'print $4}') echo $PIN 

и это показывает вам имя приложения, просто имя без идентификатора.

  • Как проверить, существует ли процесс с данным pid в Python?
  • Linux: Есть ли что-то похожее на «верх» для ввода-вывода?
  • .NET - WindowStyle = hidden vs. CreateNoWindow = true?
  • popen () альтернатива
  • запустить exe / process с stdin stdout и stderr?
  • Как найти идентификатор процесса (pid) процесса, запущенного в java?
  • Как определить завершенный процесс Windows, если у меня все еще есть его PID?
  • Как я могу получить PID родительского процесса моего приложения
  • Как служба Windows может запустить процесс при создании события Timer?
  • Почему этот процесс рушится, как только он запускается?
  • Система и прерывания, вызывающие высокий CPU
  • Давайте будем гением компьютера.