`kill -0` 有什么作用?

`kill -0` 有什么作用?

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

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

有什么kill -0 ...作用?

答案1

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

杀死(1)

$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...

杀死(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.
...

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

这可能在哪里有用?

一个明显的地方是,如果您试图确定您是否有权通过 向正在运行的进程发送信号kill。您可以在发送kill所需的实际信号之前进行检查,方法是包装检查以确保kill -0 <PID>首先允许这样做。

例子

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

$ sudo sleep 2500 &
[1] 15693

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

$ pgrep sleep
15693

现在让我们尝试这个命令,看看我们是否有权通过 发送 PID 信号kill

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

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

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

完整示例

那么我们可以做这样的事情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

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

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

$ echo $?
1

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

$ sudo ~/killer.bash 

$ echo $?
0

$ pgrep sleep
$

答案2

kill -0(或其更便携的 POSIX 变体kill -s 0)会执行发送信号的动作,但实际上并不发送信号。它的一个特点是底层C API认为外壳命令以直接的方式暴露。

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

请记住,即使存在具有预期 PID 和权限的正在运行的进程,这也不一定是您期望的进程。您期望的进程可能较早终止,并且其 PID 被重用于不相关的进程。监视进程的正确方法是让其父进程执行此操作 — 进程的 PID 在其父进程确认其死亡之前不会被重用(这就是为什么僵尸存在),因此进程的父进程可以通过 PID 可靠地识别其子进程。

答案3

告诉kill -0 $pid您进程是否$pid存在。

在片段中

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

... do something ...如果具有存储的 PID 的进程正在运行,则执行该块/path/to/file.pid- 并且 - 除非代码片段以 root 身份运行 - 如果 PID 在同一用户下运行。

POSIX标准规定了信号的作用0

如果 sig 为 0(空信号),则执行错误检查,但实际上不发送信号。空信号可用于检查pid的有效性。

杀(3p), POSIX.1-2008 - POSIX.1-2001 中的类似措辞)

请注意,POSIX 指定了kill -0kill -s 0命令行样式(杀死(1p))。

与 Kill 系统调用接口相比,该kill命令不能用于可靠地检查其他用户(作为普通用户)拥有的 PID 是否存在,例如:

$ kill -0 123
kill: kill 123 failed: no such process
$ echo $?
1

$ kill -0 1
kill: kill 1 failed: operation not permitted
$ echo $?
1

当调用kill系统调用时,我们可以通过查看值来可靠地区分这些情况errno(参见例如Python 示例)。

相关内容