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

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

if [ a process exists with $PID ]; then

    kill $PID 

fi

что соответствующее выражение для условного оператора?

9 ответов


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

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, i.e. the process with $PID is running
fi

проблема:

kill -0 $PID

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

kill -0 1

и

kill -0 $non-running-pid

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

обсуждение

ответы, обсуждающие условия убийства и гонки, точно правильно, если тело теста является "убить". Я пришел за генералом.--17-->как вы проверяете существование PID в bash".

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


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

или

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

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


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

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

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

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

[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  }' | grep 3358
3358

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

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

Второй способ: просто ищите что-то в


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


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

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  twice, exiting now..."
    exit 1
  fi
fi

echo $$ > .pid

# do things here

rm .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 }')
echo $PIN

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