如何检查进程ID(PID)是否存在
在bash脚本中,我想要执行以下操作(使用伪代码):
if [ a process exists with $PID ]; then kill $PID fi
条件语句的恰当expression是什么?
要检查进程的存在,请使用
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, ie the process with $PID is running fi
问题在于:
kill -0 $PID
是退出代码将是非零即使该pid正在运行,你没有权限杀死它。 例如:
kill -0 1
和
kill -0 $non-running-pid
有一个普通用户不可区分的(非零)退出代码,但init进程(PID 1)当然在运行。
讨论
如果testing的主体是“杀人”,那么讨论杀戮和竞赛条件的答案是完全正确的。 我来找一般的“ 你怎么testing一个PID在bash中存在 ”。
/ proc方法很有趣,但从某种意义上讲,打破了“ps”命令抽象的精神,也就是说你不需要去看/ proc,因为如果Linus决定调用“exe”文件呢?
if [ -e /proc/$PID ]
要么
if [ -n "$(ps -p $PID -o pid=)" ]
在后一种forms中, -o pid=
是只显示没有标题的进程ID列的输出格式。 非空string运算符-n
需要引号才能给出有效的结果。
ps
命令与-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 $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
kill -9 $PID || true
?
编辑:
经过几个月的思考(大约24 …)我给这里的原始想法是一个很好的黑客,但非常不可移植。 虽然它教导了Linux的一些实现细节,但它将无法在Mac,Solaris或* BSD上运行。 它甚至可能会在未来的Linux内核上失败。 请按照其他回复中的描述使用“ps”。
我认为这是一个不好的解决scheme,这对于竞争条件是开放的。 如果这个过程在你的testing和你的杀手之间死掉了怎么办? 然后杀死将失败。 那么为什么不试试在所有情况下杀死,并检查其返回值,以了解它是怎么回事?
好像你想要的
wait $PID
当$pid
完成时将返回。
否则,你可以使用
ps -p $PID
检查过程是否还活着(这比kill -0 $pid
更有效,因为即使你不拥有kill -0 $pid
,它也能工作)。
例如在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的名称。
在这里我将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存在,但由另一个应用程序使用,则可能导致“无法预料的后果”。