`kill -0` 有什么作用?

slm*_*slm 84 shell process kill

我最近在 shell 脚本中遇到了这个问题。

if ! kill -0 $(cat /path/to/file.pid); then
    ... do something ...
fi
Run Code Online (Sandbox Code Playgroud)

有什么作用kill -0 ...

slm*_*slm 101

这个有点难以收集,但如果您查看以下 2 个手册页,您将看到以下注释:

杀死(1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
Run Code Online (Sandbox Code Playgroud) 杀死(2)
$ man 2 kill
...
If sig is 0, then no signal is sent, but error checking is still performed; 
this can be used to check for the existence of a process ID or process 
group ID.
...
Run Code Online (Sandbox Code Playgroud)

因此,信号 0 实际上不会向您的进程的 PID 发送任何内容,但会检查您是否有权这样做。

这可能在哪里有用?

一个明显的地方是,如果您试图确定您是否有权通过kill. 您可以在发送kill您想要的实际信号之前进行检查,通过包装检查以确保kill -0 <PID>首先允许。

例子

假设一个进程由 root 运行,如下所示:

$ sudo sleep 2500 &
[1] 15693
Run Code Online (Sandbox Code Playgroud)

现在在另一个窗口中,如果我们运行此命令,我们可以确认该 PID 正在运行。

$ pgrep sleep
15693
Run Code Online (Sandbox Code Playgroud)

现在让我们试试这个命令,看看我们是否可以通过kill.

$ if ! kill -0 $(pgrep sleep); then echo "You're weak!"; fi
bash: kill: (15693) - Operation not permitted
You're weak!
Run Code Online (Sandbox Code Playgroud)

所以它有效,但输出从kill我们没有权限的命令中泄漏了一条消息。没什么大不了的,只需捕获 STDERR 并将其发送到/dev/null.

$ if ! kill -0 $(pgrep sleep) 2>/dev/null; then echo "You're weak!"; fi
You're weak!
Run Code Online (Sandbox Code Playgroud)

完整示例

那么我们可以做这样的事情,killer.bash

#!/bin/bash

PID=$(pgrep sleep)
if ! kill -0 $PID 2>/dev/null; then 
  echo "you don't have permissions to kill PID:$PID"
  exit 1
fi

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

现在,当我以非 root 用户身份运行上述内容时:

$ ~/killer.bash 
you don't have permissions to kill PID:15693

$ echo $?
1
Run Code Online (Sandbox Code Playgroud)

但是,当它以 root 身份运行时:

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$
Run Code Online (Sandbox Code Playgroud)

  • Prateek61 是对的。你不能在便携式脚本中使用 `pgrep`、`ps` 解析或 `test -e /proc/$PID`,但 `kill -0` 可以在任何地方使用。如果你得到一个可能过时的 PID——例如一个 `/var/run` 条目——这是检查进程是否还活着的可移植方式。 (12认同)
  • 我还要补充一点,这可用于多进程脚本,以查看进程是否仍在运行。 (10认同)

Gil*_*il' 28

kill -0(或其更便携的 POSIX 变体kill -s 0)经历了发送信号的过程,但实际上并不发送信号。这是一个特点底层C APIshell命令以简单的方式曝光。

kill -s 0 -- "$pid"因此测试是否存在具有给定 PID(或 PGID,如果$pid为负)的正在运行的进程,以及当前进程是否有权向它(进程组中的任何进程,如果为负$pid)发送信号。它主要是一种测试进程(或进程组)是否存活的方法。

请记住,即使存在具有预期 PID 和权限的正在运行的进程,这也不一定是您期望的进程。您期望的进程可能更早死亡,并且其 PID 被重用于不相关的进程。监控进程的正确方法是让它们的父进程来做——一个进程的 PID 不会被重用,直到它的父进程确认它的死亡(这就是僵尸存在的原因),所以一个进程的父进程可以通过它们的 PID 可靠地识别它的子进程。