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


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

if [ a process exists with $PID ]; then

    kill $PID 

fi

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

9 145

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), безусловно, работает.

обсуждение

ответы, обсуждающие условия убийства и расы, точно правильно, если тело теста является "убить". Я пришел искать генерала"как вы проверяете наличие 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. если система перезагружается и .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

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