如何检查进程ID(PID)是否存在

Ric*_*d H 169 bash pid process

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

if [ a process exists with $PID ]; then

    kill $PID 

fi
Run Code Online (Sandbox Code Playgroud)

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

FDS*_*FDS 240

最好的方法是:

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
Run Code Online (Sandbox Code Playgroud)

问题:

kill -0 $PID
Run Code Online (Sandbox Code Playgroud)

退出代码将是非零,即使pid正在运行,你没有权限杀死它.例如:

kill -0 1
Run Code Online (Sandbox Code Playgroud)

kill -0 $non-running-pid
Run Code Online (Sandbox Code Playgroud)

普通用户有一个难以区分的(非零)退出代码,但init进程(PID 1)肯定在运行.

讨论

如果测试的主体是"杀戮",那么讨论杀戮和种族条件的答案是完全正确的.我来找一般的" 你如何测试bash中的PID存在 ".

/ proc方法很有意思,但在某种意义上打破了"ps"命令抽象的精神,即你不需要去查看/ proc,因为如果Linus决定调用"exe"文件是什么呢?

  • 这在 BusyBox 上不起作用。OpenWrt 仅识别“w”表示“宽输出”,Alpine 仅采用“-o”来过滤输出列。[文档](https://busybox.net/downloads/BusyBox.html) 还提到了用于显示线程的“-T”。没有“-p”参数。 (4认同)
  • 你的ps -p技巧在我的ubuntu中不起作用. (2认同)
  • ps -p总是在os x中返回状态代码0,因为它在不匹配任何正在运行的进程时打印一个空的进程列表 (2认同)
  • 如果你想知道 id $PID 的进程是否存在,你可以只执行 `test -d /proc/$PID` 而不是启动其他进程。请注意,您永远无法知道进程是否存在于其他 PID 命名空间中。 (2认同)

Chr*_*röm 170

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

kill -0 $pid
Run Code Online (Sandbox Code Playgroud)

但就像@unwind说的那样,如果你要杀死它,那么就是

kill $pid
Run Code Online (Sandbox Code Playgroud)

或者你会有竞争条件.

如果要忽略文本输出kill并根据退出代码执行某些操作,则可以

if ! kill $pid > /dev/null 2>&1; then
    echo "Could not send SIGTERM to process $pid" >&2
fi
Run Code Online (Sandbox Code Playgroud)

  • 这有一个问题,如果进程不属于正在运行的用户,则可能没有权限调用kill -0.最好使用ps -p $ PID>/dev/null 2>&1,即使您没有发送信号的权限,也可以查看进程状态. (39认同)
  • `kill`有点不好用,因为它不一定会杀死这个过程.它只是向进程发送信号.`kill $ PID`相当于`kill -15 $ PID`,它向进程发送信号15,SIGTERM,这是一个终止指令.没有信号0,这是一个特殊的值告诉`kill`只是检查一个信号是否可以被发送到进程,这大多数或多或少等同于检查它是否存在.请参阅http://linux.die.net/man/2/kill和http://linux.die.net/man/7/signal (21认同)
  • @mckoss:在那种情况下,无论如何他都无法杀死它. (6认同)
  • @sdaau:再读一遍。如果你无论如何都要杀死它,那么就杀死它,否则你会遇到竞争条件。但是是的,退出代码 0 意味着当时可以向它发送信号。这并不意味着您可以确定可以在一毫秒后向它发送信号。 (3认同)
  • 因此,我想-要使用`kill -0`,实际上我必须这样做:`kill -0 25667; echo $?`-然后如果我返回一个“ 0”,则具有该PID的进程可以被杀死;如果过程PID(例如)不存在,则$$将为1,表示失败。那是对的吗? (2认同)
  • 如果由于某种原因 $PID 为 0(例如,它应该从 pid 文件中读取,但文件丢失并且某些逻辑决定放置一个“0”),则 kill -0 0 返回错误代码 0,就好像进程pid存在!小心这个陷阱。 (2认同)

use*_*246 63

if [ -n "$PID" -a -e /proc/$PID ]; then
    echo "process exists"
fi
Run Code Online (Sandbox Code Playgroud)

要么

if [ -n "$(ps -p $PID -o pid=)" ]
Run Code Online (Sandbox Code Playgroud)

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

  • 如果 `$PID` 为空,那么 `[ -e /proc/$PID ]` 仍然会返回 true,因为 `/proc/` 目录仍然存在。 (3认同)
  • 第二种方法也适用于 Mac,这是一个额外的优点(Mac OS X 没有 /proc FS)。但是,您可以避免使用子 shell,并在 Mac 和 Linux 上使用它: `if ps -p"$PID" -o "pid=" >/dev/null 2>&1; 然后回显“进程正在运行...”;菲` (2认同)

ohe*_*ala 33

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

$ ps -p 3531
  PID TTY          TIME CMD
 3531 ?        00:03:07 emacs
Run Code Online (Sandbox Code Playgroud)


elc*_*uco 11

你有两种方式:

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

[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
Run Code Online (Sandbox Code Playgroud)

现在所有的例子都将寻找PID 3358.

第一种方法:在第二列中运行"ps aux"和grep for PID.在这个例子中我寻找firefox,然后是它的PID:

[root@pinky:~]# ps aux | awk '{print $2 }' | grep 3358
3358
Run Code Online (Sandbox Code Playgroud)

所以你的代码将是:

if [ ps aux | awk '{print $2 }' | grep -q $PID 2> /dev/null ]; then
    kill $PID 
fi
Run Code Online (Sandbox Code Playgroud)

第二种方式:只需在/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
Run Code Online (Sandbox Code Playgroud)

所以你的代码将是:

if [ -f /proc/$PID/exe ]; then
    kill $PID 
fi
Run Code Online (Sandbox Code Playgroud)

顺便说一句:什么错了kill -9 $PID || true


编辑:

在考虑了几个月之后..(大约24 ...)我在这里给出的最初想法是一个很好的黑客,但非常不可移植.虽然它教授了Linux的一些实现细节,但它无法在Mac,Solaris或*BSD上运行.它甚至可能在未来的Linux内核上失败.请 - 使用"ps",如其他回复中所述.


unw*_*ind 8

我认为这是一个糟糕的解决方案,可以满足竞争条件.如果这个过程在你的测试和你的杀戮之间死亡怎么办?然后杀死将失败.那么为什么不在所有情况下尝试杀死,并检查其返回值以了解它是如何进行的?

  • 不要随便'杀死-9`.这只会立即杀死这个过程,让它无法自行清理.而是使用相当于`kill -15`的`kill`.如果这不起作用,你应该找出原因,并且只作为最后的手段使用`kill -9`. (13认同)

Gag*_*ami 6

好像你要

wait $PID
Run Code Online (Sandbox Code Playgroud)

$pid完成后会返回。

否则你可以使用

ps -p $PID
Run Code Online (Sandbox Code Playgroud)

来检查该进程是否仍然存在(这比kill -0 $pid因为即使您不拥有该pid也会起作用而有效)。

  • 等待不是那么有效,因为进程应该是当前 shell 的子进程,否则它会给出:`pid 123 is not a child of this shell` (3认同)