222

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

if [ a process exists with $PID ]; then

    kill $PID 

fi

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

4

11 回答 11

312

最好的方法是:

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

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文件命名为别的东西怎么办?

于 2013-04-02T21:29:31.177 回答
205

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

kill -0 $pid

但正如@unwind 所说,如果您希望它在任何情况下终止,那么只需

kill $pid

否则,您将遇到竞争条件,该过程可能在第一个kill -0.

如果你想忽略的文本输出kill并根据退出代码做一些事情,你可以

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi
于 2010-06-15T09:40:23.260 回答
78

在Linux 等实现procfs/proc/$PID接口的系统上,你可以只检查是否存在:

if test -d /proc/"$PID"/; then
    echo "process exists"
fi

否则你可以使用ps程序:

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

在后一种形式中,-o pid=是一种仅显示进程 ID 列而没有标题的输出格式。非空字符串运算符需要引号-n才能给出有效结果。

于 2014-06-24T13:23:25.767 回答
40

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

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs
于 2010-06-15T09:40:20.453 回答
12

你有两种方法:

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

[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 auxgrep获取第二列中的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


编辑:

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

于 2010-06-15T09:40:26.033 回答
8

好像你想要

wait $PID

完成后将返回$pid

否则你可以使用

ps -p $PID

检查进程是否还活着(这比kill -0 $pid因为即使你不拥有 pid 它也能工作更有效)。

于 2014-05-19T09:00:41.400 回答
7

我认为这是一个糟糕的解决方案,它为竞争条件开辟了道路。如果进程在您的测试和您调用 kill 之间终止怎么办?然后杀死将失败。那么为什么不在所有情况下都尝试杀死,并检查它的返回值以了解它是如何进行的呢?

于 2010-06-15T09:32:48.247 回答
1

例如,在 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 的名称。

于 2014-10-16T09:39:10.783 回答
1

通过pid

pgrep [pid] >/dev/null

名称

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

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

于 2021-02-19T06:28:50.320 回答
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 存在但被不同的应用程序使用,这可能会导致“不可预见的后果”。

于 2015-12-04T15:41:40.233 回答
-1

从@FDS 的答案中学习并投票赞成,因为它很好而且正确。但是,这里有一个我觉得更容易阅读和理解的表格:

pid=1234
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
    echo "PID $pid exists and is running."
fi

更新:shellcheck check_if_pid_exists.sh告诉我实际上应该以另一种方式(如@FDS 所示)以避免冗余:

pid=1234
if ps --pid "$pid" > /dev/null; then
    echo "PID $pid exists and is running."
fi

所以……也许我以后会适应那样做。

无论如何,这是一个完整的、可运行的程序(我想这是我在这里的贡献):

check_if_pid_exists.sh:

#!/usr/bin/env bash

pid=1234

if [ "$#" -gt 0 ]; then
    # At least 1 argument was passed in, so assume it is the PID
    pid="$1"
fi

# Try to print the process (`ps`) information for this PID. Send it to
# /dev/null, however, so we don't actually have to look at it. We just want
# the return code, `$?`, which will be 0 if the process exists and some other
# number if not.
ps --pid "$pid" > /dev/null
if [ "$?" -eq 0 ]; then
    echo "PID $pid exists and is running."
else
    echo "PID $pid does NOT exist."
fi

示例运行调用和输出:

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 28876
PID 28876 exists and is running.

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh
PID 1234 does NOT exist.

eRCaGuy_hello_world/bash$ ./check_if_pid_exists.sh 5678
PID 5678 does NOT exist.
于 2022-02-15T22:49:36.547 回答