在bash脚本中,我想做以下事情(在伪代码中):

if [ a process exists with $PID ]; then

    kill $PID 

fi

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


当前回答

你有两种方法:

让我们开始寻找一个特定的应用程序在我的笔记本电脑:

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

第一种方法:为第二列中的PID运行ps aux和grep。在这个例子中,我查找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

顺便说一句:杀-9 $PID ||有什么不对吗?


编辑:

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

其他回答

你有两种方法:

让我们开始寻找一个特定的应用程序在我的笔记本电脑:

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

第一种方法:为第二列中的PID运行ps aux和grep。在这个例子中,我查找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

顺便说一句:杀-9 $PID ||有什么不对吗?


编辑:

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

最好的方法是:

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的问题是,即使进程正在运行,并且您没有权限杀死它,退出码也将是非零。例如:

kill -0 $known_running_pid

and

kill -0 $non_running_pid

有一个非零的退出码,这些退出码对于普通用户来说是难以区分的,但其中一个假设正在运行,而另一个则没有。


部分相关的,由AnrDaemon提供的附加信息:init进程(PID 1)肯定在所有Linux机器上运行,但不是所有POSIX系统都是Linux。PID 1不保证存在:

kill -0 1 
-bash: kill: (1) - No such process … 

讨论

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

/proc方法很有趣,但在某种意义上破坏了ps命令抽象的精神,也就是说,你不需要在/proc中查找,因为如果Linus决定调用其他的exe文件怎么办?

我认为这是一个糟糕的解决方案,这为比赛条件打开了大门。如果进程在测试和终止调用之间停止了,该怎么办?那么杀戮就会失败。那么,为什么不在所有情况下都尝试kill,并检查它的返回值以了解它是如何运行的呢?

ps命令和-p $PID可以做到这一点:

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

看起来你想要

wait $PID

当$pid结束时返回。

否则你可以使用

ps -p $PID

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