Bash 如何检查进程id(PID)是否存在
在bash脚本中,我希望执行以下操作(在伪代码中):Bash 如何检查进程id(PID)是否存在,bash,process,pid,Bash,Process,Pid,在bash脚本中,我希望执行以下操作(在伪代码中): 条件语句的合适表达式是什么?我认为这是一个糟糕的解决方案,它为竞争条件打开了大门。如果进程在测试和调用kill之间终止,该怎么办?那么杀戮就会失败。那么,为什么不在所有情况下都尝试kill,并检查其返回值以了解其运行情况呢?ps命令和-p$PID可以做到这一点: $ ps -p 3531 PID TTY TIME CMD 3531 ? 00:03:07 emacs 要检查是否存在进程,请使用 kill
条件语句的合适表达式是什么?我认为这是一个糟糕的解决方案,它为竞争条件打开了大门。如果进程在测试和调用kill之间终止,该怎么办?那么杀戮就会失败。那么,为什么不在所有情况下都尝试kill,并检查其返回值以了解其运行情况呢?
ps
命令和-p$PID
可以做到这一点:
$ ps -p 3531
PID TTY TIME CMD
3531 ? 00:03:07 emacs
要检查是否存在进程,请使用
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
你有两种方法:
让我们从在我的笔记本电脑中查找特定应用程序开始:
[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
if [ -f /proc/$PID/exe ]; 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 [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
kill $PID
fi
if [ -f /proc/$PID/exe ]; then
kill $PID
fi
顺便说一句:kill-9$PID | | true
有什么问题
编辑: 考虑了几个月后。。(大约24…)我在这里给出的最初想法是一个不错的破解,但非常不可移植。虽然它教授了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
退出代码将为非零,即使pid正在运行,并且您没有终止它的权限。例如:
kill -0 1
及
对于普通用户,有一个不可区分(非零)的退出代码,但init进程(PID 1)肯定正在运行
讨论
如果测试的主体是“杀死”,那么讨论杀死和种族条件的答案是完全正确的。我是来找“如何在bash中测试PID的存在性”这篇文章的
/proc方法很有趣,但在某种意义上打破了“ps”命令抽象的精神,也就是说,您不需要查看/proc,因为如果Linus决定将“exe”文件调用为其他文件怎么办?这似乎是您想要的
wait $PID
当$pid
完成时返回
否则,您可以使用
ps -p $PID
检查进程是否仍处于活动状态(这比kill-0$pid
更有效,因为即使您没有pid,它也会工作)
或
在后一种形式中,
-o pid=
是一种输出格式,只显示没有标题的进程ID列。引号用于非空字符串运算符-n
以给出有效结果。例如,在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
#/bin/bash
if[-f.pid];然后
读取pid<.pid
echo$pid
ps-p$pid>/dev/null
r=$?
如果[$r-等式0];然后
echo“$pid当前正在运行,未执行$0两次,正在退出…”
出口1
fi
fi
echo$$>.pid
#在这里做事
rm.pid
注意:存在竞争条件,因为它不检查pid的调用方式。如果系统重新启动并且.pid存在,但被其他应用程序使用,这可能会导致“不可预见的后果”。
pgrep [pid] >/dev/null
pgrep -u [user] -x [name] >/dev/null
通过名称:
pgrep [pid] >/dev/null
pgrep -u [user] -x [name] >/dev/null
“-x”表示“完全匹配”。+1不幸的是,kill(1)的退出代码没有区分不同的错误情况(看起来它为每个未发出信号的进程增加一个退出值)。如果OP不介意编写他们自己的kill(2)包装器,他可以让它在kill(2)调用失败后,根据ERRNO的值以不同的值退出。目前我只是在执行kill-9,没有检查-如果它不存在,我只会得到一个错误“process not exist”,这不是很整齐。我该如何测试发生了什么?不要不小心
kill-9
。这会立即扼杀整个过程,使其没有机会自行清理。改为使用kill
,这相当于kill-15
。如果这不起作用,您应该找出原因,并且仅作为最后手段,使用kill-9
kill
有点命名错误,因为它不一定会终止进程。它只是向进程发送一个信号kill$PID
相当于kill-15$PID
,它向进程发送信号15,SIGTERM,这是一条终止指令。没有信号0,这是一个特殊值,告诉kill
只检查信号是否可以发送到进程,这在大多数情况下或多或少等同于检查它是否存在。请参阅,问题在于,如果进程不属于正在运行的用户,则您可能没有调用kill-0的权限。最好使用ps-p$PID>/dev/null 2>&1,它允许您查看进程状态,即使您没有发送信号的权限。@mckoss:在这种情况下,他无论如何也不能杀死它。因此,我猜-要使用kill-0
,实际上我必须这样做:kill-0 25667;echo$?
-然后如果我得到一个0
返回,那么可以终止具有该PID的进程;如果进程PID(比如)不存在,$?
将是1
,表示失败。是这样吗?@sdau:请再读一遍。如果你无论如何都要杀了它,那就杀了它,否则你会有一个比赛条件。但是,是的,退出代码为0意味着当时可以向其发送信号。这并不意味着你可以肯定