我最近在 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 -0
和kill -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 示例)。