如何检查进程ID(PID)是否存在

时间:2010-06-15 09:30:27

标签: bash process pid

在bash脚本中,我想执行以下操作(使用伪代码):

if [ a process exists with $PID ]; then

    kill $PID 

fi

条件语句的适当表达式是什么?

11 个答案:

答案 0 :(得分:225)

最好的方法是:

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)肯定在运行。

讨论

如果测试的主体是“杀戮”,那么讨论杀人和竞争条件的答案是完全正确的。我来找一般的“你如何测试bash中的PID存在”。

/ proc方法很有意思,但在某种意义上打破了“ps”命令抽象的精神,即你不需要去查看/ proc,因为如果Linus决定调用“exe”文件是什么呢?

答案 1 :(得分:161)

要检查进程是否存在,请使用

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 :(得分:57)

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

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

在后一种形式中,-o pid=是一种输出格式,仅显示没有标题的进程ID列。对于非空字符串运算符-n,引号为necessary以提供有效结果。

答案 3 :(得分:31)

使用ps

-p $PID命令可以执行此操作:

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

答案 4 :(得分:10)

您有两种方式:

让我们首先在笔记本电脑中寻找特定的应用程序:

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

BTW:kill -9 $PID || true出了什么问题?


编辑:

在考虑了几个月之后..(大约24 ...)我在这里给出的最初想法是一个很好的黑客,但非常不可移植。虽然它教授了Linux的一些实现细节,但它无法在Mac,Solaris或* BSD上运行。它甚至可能在未来的Linux内核上失败。请 - 使用“ps”,如其他回复中所述。

答案 5 :(得分:7)

我认为这是一个糟糕的解决方案,可以满足竞争条件。如果这个过程在你的测试和你的杀戮之间死亡怎么办?然后杀死将失败。那么为什么不在所有情况下尝试杀死,并检查其返回值以找出它是如何进行的?

答案 6 :(得分:3)

好像你想要

wait $PID

将在$pid完成时返回。

否则你可以使用

ps -p $PID

检查进程是否仍然有效(这比kill -0 $pid更有效,因为即使您不拥有pid,它也会有效。)

答案 7 :(得分:1)

通过pid

pgrep [pid] >/dev/null

名称

pgrep -u [user] -x [name] >/dev/null

-x”表示“完全匹配”。

答案 8 :(得分:0)

例如,在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

,它会显示应用程序的名称,只显示没有ID的名称。

答案 9 :(得分:0)

这里我将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存在但被其他应用程序使用,则可能会导致“不可预见的后果”。

答案 10 :(得分:0)

下面的代码检查我的进程是否正在运行,如果不执行任何操作。

仅在流程未运行时,才每小时检查一次来自Amazon SQS的新消息。

#!/bin/bash
PID=$(ps aux | grep '/usr/bin/python2.7 manage.py SES__boto3_sqs_read' | grep -v grep | awk '{print $2}')
if [[ -z $PID ]]; then
    /usr/bin/python2.7 /home/brian/djcode/proyectoONE/manage.py SES__boto3_sqs_read
else
    echo "do nothing, just smile =)"
fi
exit $?