在一个shell脚本中,`kill -0 $pid`是什么意思?

150

基本上,“0”代表什么信号,因为这里我看到的SIGNAL编号是从1开始的。


3
http://linux.die.net/man/1/kill - Lee
3
请参考Unix.SE中文问题的变体,它与kill 0(没有破折号)不同,这里有解释这里这里 - Adam Katz
6个回答

146

发送信号0到给定的PID仅检查是否有任何具有给定PID的进程正在运行,并且您有权限向其发送信号。

有关更多信息,请参见以下手册页:

kill(1)
$ man 1 kill
...
If sig is 0, then no signal is sent, but error checking is still performed.
...
杀死进程的系统调用(system call)函数。
$ 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.
...

7
如果有的话,这些信息所在的位置高度依赖于系统。在最近的基于Debian的系统上,请使用 man 2 kill 来查看。 - Todd A. Jacobs
2
man 1 killman 2 kill在我的Fedora 20系统上都有。虽然很难发现,但它们都埋藏在这些手册页中。 - slm
或者可以依赖于POSIX手册:如果sig为0(空信号),则会执行错误检查,但实际上不会发送任何信号。空信号可用于检查pid的有效性。http://pubs.opengroup.org/onlinepubs/009695399/functions/kill.html - taddy hoops
2
我觉得man 2 kill命令超出了第一修正案的范畴 :) - JBaczuk

134

这是一个好问题的原因

因为很难找到有关这个特殊信号的文档。尽管其他人所说,但在基于Debian的系统中,man 1 kill 中唯一提到这个信号的地方是:

尤其有用的信号包括HUP、INT、KILL、STOP、CONT和0。

这并不是特别有帮助,特别是如果你不知道这个信号的作用。它也没有列在 kill -l 的输出中,因此除非您已了解该信号,否则您将不知道它的存在。

如何查找该信号的文档

在Debian和Ubuntu系统上,man 2 kill 的输出部分如下:

如果sig为0,则不发送信号,但仍执行错误检查;这可以用于检查进程ID或进程组ID是否存在。

它的用途

您可以使用 kill -0 来检查进程是否正在运行。请考虑以下示例。

# Kill the process if it exists and accepts signals from
# the current user.
sleep 60 &
pid=$!
kill -0 $pid && kill $pid

# Check if a PID exists. When missing, this should result
# in output similar to:
#    bash: kill: (6228) - No such process
#    Exit status: 1
kill -0 $pid; echo "Exit status: $?"

您还可以使用kill -0来确定当前用户是否有权限向给定进程发送信号。例如:

# See if you have permission to signal the process. If not,
# this should result in output similar to:
#     bash: kill: (15764) - Operation not permitted
#     Exit status: 1
sudo sleep 60 &
kill -0 $!; echo "Exit status: $?"

在 Mac 和 BSD 上,它也在“kill(2)”中有记录。以下是代码片段:“kill()”函数向进程或一组进程发送由sig指定的信号。通常,Sig将是在“sigaction(2)”中指定的信号之一。然而,值为0将导致执行错误检查(不发送任何信号)。这可以用于检查pid的有效性。 - lukecampbell
8
这应该成为被采纳的答案,比另一个答案好多了。关于信号0的文档很难找到。它被埋在kill手册中:“如果信号是0,则不发送信号,但仍执行错误检查。” - slm

10

kill -0 $pid是检查具有进程id(pid)的进程是否存在。

在使用kill -0 $pid检查进程是否存在时要小心,因为:

  1. 一旦目标进程退出,它的pid可能会分配给其他新创建的进程。(因此,人们不能确定特定的进程是否仍在运行)

  2. 在僵尸进程的情况下,子进程等待父进程调用wait。 在这种情况下,它保留$pid并给出肯定的结果,而该进程未运行。


6

该命令检查 $pid 中的进程是否正在运行。


1
手册上说: “如果sig为0,则不发送信号,但仍执行错误检查。” 这里指的是哪些错误检查? - gjain
2
-1,因为具有PID“$pid”的进程可能正在运行,但您没有权限向其发送信号。 - dwalter
3
如果没有权限,您将获得EPERM;如果不存在,则会获得ESRCH。kill(1)将为每个错误打印不同的错误。因此,无论您是否有发送信号的权限,都可以确定pid是否处于活动状态。此外,kill -0 的典型用途是查看pid是否处于活动状态,即使它并不总是被正确使用。我认为这个答案是正确的(拼写除外)。 - camh
3
@camh:不,无论哪种情况,kill -0 $pid 命令的返回值都是相同的。它将返回 1,因此如果您没有权限向进程发送信号,则无法仅通过解析 kill 命令的输出来判断该进程是否正在运行。编辑:是的,我知道大多数情况下它用于检查进程是否存活,但是除非您可以保证具有发送信号的权限(例如:是 root 用户),否则这是错误的。 - dwalter
2
@dwalter:我的观点是答案是正确的。你试图挑剔并指出还有另一个错误情况,但我告诉你,从技术上讲,答案也涵盖了那种情况,因为kill bash内置命令(问题标记为bash)在stderr上输出错误类型,并在其返回代码中指示错误。也就是说,“此命令检查$pid中的PID进程是否存活”如果你正确解释输出,那么完全正确。[如果你没有给答案打-1分,我不会评论。否则你的评论是有效的]。 - camh
显示剩余2条评论

1
"

kill -0 $pid 用于检查进程 $pid 是否在运行。但这可能会有些棘手,因为一旦进程退出并启动新进程,进程ID就可能被重新分配。

可以使用 killall -0 <process name> 来获取特定进程是否正在运行的信息。

"

1

发送EXIT信号或0给一个进程将会:

  1. 检查进程是否存在。
  2. 对进程进行各种错误检查(PID、PGID等)。
  3. 成功时不会向stdout发送任何输出。
  4. 如果有问题,会向stderr发送错误消息。
  5. 如果进程处于僵尸状态(即Zombie),则会给出错误的结果。

更明确地说,一个对你的shell脚本有用的函数是:

function isProcess ()
{
    kill -s EXIT $1 2> /dev/null
}

这将在成功后不向标准输出stdout 返回任何文本,但在失败时向标准错误stderr 返回错误消息(但我已将该错误消息重定向到/dev/null)。 如果您担心死掉/僵尸进程状态,则需要使用ps,最好使用--no-headers开关。
#!/bin/ksh

function trim ()
{
    echo -n "$1" | tr -d [:space:]
}

function getProcessStatus ()
{
    trim $(ps -p $1 -o stat --no-headers)
}

function isZombie ()
{
    typeset processStatus=$(getProcessStatus $1)

    [[ "$processStatus" == "Z" ]]
    return $?
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接