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

В bash script, я хочу сделать следующее (в псевдокоде):

if [ a process exists with $PID ]; then

    kill $PID 

fi

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

Ответ 1

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

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

Ответ 2

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

if ps -p $PID > /dev/null
then
   echo "$PID is running"
   # Do something knowing the pid exists, i.e. 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 чем-то еще?

Ответ 3

if [ -e /proc/$PID ]

или

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

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

Ответ 4

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

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

Ответ 5

У вас есть два способа:

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

[[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

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


EDIT:

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

Ответ 6

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

Ответ 7

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

wait $PID

который вернется, когда заканчивается $pid.

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

ps -p $PID

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

Ответ 8

Например, в 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

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

Ответ 9

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

#!/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 существует, но используется другим приложением, это может привести к "непредвиденным последствиям".