当我试图向朋友展示工作控制力时,我遇到了意想不到的行为。对于某些命令,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
kill
Bourne Again shell 手册中没有记录内置函数在这些情况下真正执行的操作,但 Z shell 和 Korn shell 手册中记录了它:
- 科恩壳:
如果发送的信号是
TERM
(终止)或HUP
(挂断),则作业或进程CONT
停止时将发送(继续)信号。 - Z壳:
如果发送的信号不是
KILL
或CONT
,则作业CONT
停止时将发送一个信号。
Bourne Again shell 手册应该类似如下:
如果发送的信号是TERM
orHUP
并且目标进程是作业的一部分,则CONT
当作业停止或作业控制在当前终端中不可用时,将向该作业发送信号。
因为这就是它实际上所做的。