为什么kill对作业号的作用与对PID的作用不同?

为什么kill对作业号的作用与对PID的作用不同?

当我试图向朋友展示工作控制力时,我遇到了意想不到的行为。对于某些命令,kill 适用于作业号,但不适用于进程 ID。

我期望的行为的一个例子:

user@host:~$ sleep 1h &
[1] 4518
user@host:~$ sleep 2h &
[2] 4519
user@host:~$ kill %2
[2]+ Terminated   sleep 2h
user@host:~$ kill 4518
[1]+ Terminated   sleep 1h

在这两种情况下,睡眠都会终止。一份按作业编号,一份按 PID。现在我最初使用命令 cat 尝试了这一点,但它没有按预期工作:

user@host:~$ cat &
[1] 4521
user@host:~$ cat &
[2] 4522

[1]+ Stopped   cat
user@host:~$ kill %2
[2]+ Terminated   cat
user@host:~$ kill 4521
user@host:~$ jobs
[1]+ Stopped   cat
user@host:~$ kill 4521
user@host:~$ jobs
[1]+ Stopped   cat
user@host:~$ kill %1
[1]+ Terminated   cat

所以kill对我的进程的PID不起作用,但它对作业号起作用。我认为这不应该发生。为什么会这样呢?

我正在使用 Debian 9 和 bash 4.4.12(1)-release。

编辑:在尝试解决此问题的过程中,我意识到 cat 被“停止”的状态可能会使其对默认信号 SIGTERM 没有响应。但如果这是真的,那么终止命令应该失败并显示进程 ID 和作业号。不应该吗?

答案1

killBourne Again shell 手册中没有记录内置函数在这些情况下真正执行的操作,但 Z shell 和 Korn shell 手册中记录了它:

  • 科恩壳:
    如果发送的信号是TERM(终止)或HUP(挂断),则作业或进程CONT停止时将发送(继续)信号。
  • Z壳:
    如果发送的信号不是KILLCONT,则作业CONT停止时将发送一个信号。

Bourne Again shell 手册应该类似如下:

如果发送的信号是TERMorHUP并且目标进程是作业的一部分,则CONT当作业停止或作业控制在当前终端中不可用时,将向该作业发送信号。

因为这就是它实际上所做的。

相关内容