Как проверить, существует ли идентификатор процесса (PID) - PullRequest
163 голосов
/ 15 июня 2010

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

if [ a process exists with $PID ]; then

    kill $PID 

fi

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

Ответы [ 10 ]

231 голосов
/ 03 апреля 2013

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

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

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

ОБСУЖДЕНИЕ

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

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

165 голосов
/ 15 июня 2010

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

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
60 голосов
/ 24 июня 2014
if [ -n "$PID" -a -e /proc/$PID ]; then
    echo "process exists"
fi

или

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

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

33 голосов
/ 15 июня 2010
Команда

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

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs
11 голосов
/ 15 июня 2010

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

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

[root@pinky:~]# 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:

[root@pinky:~]# 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» в этом примере, но вы можете использовать что-нибудь еще.

[root@pinky:~]# 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", как описано в других ответах.

8 голосов
/ 15 июня 2010

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

5 голосов
/ 19 мая 2014

Похоже, вы хотите

wait $PID

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

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

ps -p $PID

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

1 голос
/ 19 ноября 2018
Приведенный ниже код

проверяет, работает ли мой процесс, если ничего не делает.

давайте проверять новые сообщения от Amazon SQS только каждый час и только если процесс не запущен.

0 голосов
/ 04 декабря 2015

здесь я сохраняю 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 существует, но используется другим приложением, это может привести к «непредвиденным последствиям».

0 голосов
/ 16 октября 2014

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

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

...