kill -0是做什么的?


61

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

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

怎么kill -0 ...办?


2
如果您对Bash的B / w trap命令与0与信号0之间的差异感到困惑,请参阅此处kill陷阱命令中的信号0是什么?
slm

Answers:


76

收集起来有些困难,但是如果您查看以下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
$

9
我还要添加此代码,以用于多进程脚本,以查看进程是否仍然存在。
prateek61

1
@slm很高兴找到。现在在我正在编写的脚本中使用此逻辑,谢谢。
111 ---

12
Prateek61是正确的。您不能使用pgrepps解析或test -e /proc/$PID在便携式便笺中使用,但kill -0可以在任何地方使用。如果给您的PID可能是陈旧的(例如,/var/run条目),则这是检查过程是否仍然有效的便携式方法。
沃伦·杨

1
除了告诉您PID是否还处于活动状态之外,它还可以有效地告诉您PID是否仍在您的UID中运行进程,因为您无权将信号发送到其他UID(除非您是root用户)。由于PID重用,这使得误报的可能性较小。
Barmar 2014年

失败kill -0 $(pgrep sleep)不一定意味着您很虚弱,如果没有sleep命令在运行,或者有多个命令无法杀死,或者其中一个睡眠在pgrep和kill之间死掉,则失败将返回false。命令正在运行。
斯特凡Chazelas

22

kill -0(或更便携的POSIX变体kill -s 0)通过发送信号的过程进行操作,但实际上并未发送信号。这是一个功能基础C APIshell命令以简单的方式公开。

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

请记住,即使正在运行的进程具有预期的PID和权限,也不一定是您期望的进程。您期望的进程可能会更早死亡,并且其PID会被重新用于无关的进程。监视进程的正确方法是让其父进程执行-进程的PID在父进程确认其死亡之前不会重复使用(这就是存在僵尸的原因),因此进程的父进程可以通过其PID可靠地标识其子进程。


0

kill -0 $pid如果一个进程有告诉你$pid的存在。

在摘要中

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

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

POSIX标准指定了0信号的作用:

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

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

需要注意的是POSIX同时指定kill -0kill -s 0命令行方式(杀死(1P))。

与kill syscall接口相反,该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 syscall时,可以通过查看该errno值来可靠地区分这些情况(例如,参见Python Example)。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.