Answers:
要检查是否存在进程,请使用
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
kill
之所以被错误命名,是因为它不一定会终止该过程。它只是向过程发送信号。 kill $PID
等价于kill -15 $PID
,它向进程发送信号15 SIGTERM,这是终止指令。没有信号0,这是一个特殊的值,告诉kill
您仅检查是否可以将信号发送到进程,在大多数情况下,这或多或少地等同于检查它是否存在。参见linux.die.net/man/2/kill和linux.die.net/man/7/signal
kill -0
实际上,我必须这样做:kill -0 25667 ; echo $?
-然后,如果我得到了0
返回,则具有该PID的进程可以被杀死;如果过程PID(例如)不存在,$?
则将为1
,表示失败。那是对的吗?
最好的方法是:
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”文件怎么办?
-p
至少在那种情况下,这是不必要的。ps $PID
具有完全相同的结果。
if [ -n "$PID" -a -e /proc/$PID ]; then
echo "process exists"
fi
要么
if [ -n "$(ps -p $PID -o pid=)" ]
在后一种形式中,-o pid=
是一种输出格式,仅显示没有标题的进程ID列。非空字符串运算符必须使用引号-n
才能给出有效结果。
if ps -p"$PID" -o "pid=" >/dev/null 2>&1; then echo "Process is running..."; fi
ps
平台之间的选项和功能往往会有所不同,因此它仍然不是完全可移植的。
$PID
为空,则[ -e /proc/$PID ]
由于/proc/
目录仍然存在,因此仍将返回true 。
您有两种方法:
让我们从在笔记本电脑中查找特定的应用程序开始:
[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
顺便说一句:kill -9 $PID || true
怎么了?
编辑:
在考虑了几个月之后..(大约24 ...),我在这里给出的最初想法是一个不错的技巧,但是非常难以移植。尽管它讲授了Linux的一些实现细节,但是它将无法在Mac,Solaris或* BSD上运行。它甚至可能在未来的Linux内核上失败。请-使用其他回复中所述的“ ps”。
/proc/$PID/exe
不是常规文件。因此,[ -f /proc/$PID/exe ]
将始终返回false
结果。尝试[ -h /proc/$PID/exe ]
。
我认为这是一个糟糕的解决方案,会在比赛条件下出现。如果该过程在您的测试和要求杀死之间死掉了怎么办?然后杀死将失败。那么,为什么不尝试在所有情况下都执行kill并检查其返回值以了解其执行情况呢?
kill -9
。这只是立即终止了该进程,因此没有机会自行清理。而是使用kill
等效于kill -15
。如果那行不通,您应该找出原因,并且只能作为最后的选择kill -9
。
在这里,我将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,但被其他应用程序使用,则可能导致“无法预料的后果”。
例如,在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的名称。
pidof
不会返回负数,因为负PID毫无意义,并且您无法杀死init
,因此您的条件是毫无意义的(此外,您需要转义>
以防止其执行重定向)。您想检查结果是否为空,但是,当然,像其他任何不错的工具一样,pidof
设置退出代码来告诉您它是否有效,因此正确的解决方案是- if Pid=$(pidof 'process_name'); then ...
或(如果Pid
以后不再需要该值)if pidof 'process_name'; then...
下面的代码检查我的进程是否正在运行,如果没有执行任何操作。
让我们仅在流程未运行时每小时检查一次来自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 $?