我运行命令(Xorg & sleep 3; xeyes) &
来测试 Xorg,并将其分组到单个子 shell 后台作业中,以便于管理。这可以正常工作,并在 3 秒后在新的 Xorg 会话中打开 xeyes。
运行该命令后,我将得到如下输出:
[1] 635
运行检查新进程后ps -ef
,我将得到如下输出:
root 635 361 0 4:52 tty1 00:00:00 -bash
root 636 365 0 4:52 tty2 00:00:00 /usr/lib/Xorg
root 639 365 0 4:52 tty1 00:00:00 xeyes
这似乎是一个非常标准的输出,并且符合预期。验证我的 X 服务器按预期工作后,我尝试使用kill %1
.运行此命令后,我的流程现在如下所示:
root 636 1 0 4:52 tty2 00:00:00 /usr/lib/Xorg
为什么 Xorg 无法退出?为什么子 shell 成功退出,正确关闭 xeyes,但没有带上 Xorg?为什么Xorg的父进程现在变成了1而不是子shell?子 shell 不应该在退出时向其所有子进程发送终止信号吗?
此外,如果我用 杀死该组kill 635
(许多资源说这应该相当于 )kill %1
,我的进程状态会更加奇怪:
root 636 1 0 4:52 tty2 00:00:00 /usr/lib/Xorg
root 639 1 0 4:52 tty1 00:00:00 xeyes
什么???为什么两个进程现在都无法退出,并且现在都是 PID 1 的子进程?这是怎么回事,我做错了什么?
除了告诉我该怎么做之外,对这里到底发生了什么的深入解释将不胜感激。
答案1
如果您想观察作业控制,您需要使用列出进程组 ID 和会话 ID-j
的选项。ps
在这里,我看到:
[...]
UID PID PPID PGID SID C STIME TTY TIME CMD
chazelas 6805 4172 6805 6805 0 06:47 pts/7 00:00:00 /bin/zsh
chazelas 6825 6805 6825 6805 0 06:48 pts/7 00:00:00 xeyes
root 6826 6825 6826 6826 0 06:48 tty2 00:00:00 /usr/lib/xorg/Xorg :4
[...]
您看到的Xorg
是 的子 shell,xeyes
因为我的 shell 比子 shell 的进程更优化,并且在子 shell 的进程中bash
运行,因为它是子 shell 的最后一个命令。xeyes
不,子 shell 在终止时不会杀死它的子 shell,这会使 shell 无法使用(这里很明显它不能,因为子 shell 已被替换xeyes
)。
同样在bash
:
$ ps -Afj
[...]
UID PID PPID PGID SID C STIME TTY TIME CMD
chazelas 7230 6805 7230 6805 0 06:54 pts/7 00:00:00 bash
chazelas 7246 7230 7246 6805 0 06:54 pts/7 00:00:00 bash
root 7247 7246 7247 7247 2 06:54 tty2 00:00:00 /usr/lib/xorg/Xorg :4
chazelas 7274 7246 7246 6805 0 06:54 pts/7 00:00:00 xeyes
[...]
有一个额外的无用bash
进程,只是等待xeyes
终止,之后不会执行任何操作,但其他方面与 中相同zsh
,您会看到 shell 已经创建了一个新的进程组(6825 for zsh
, 7246
for bash
),但Xorg
不是在该进程组中。
这不是因为&
after Xorg
,在子 shell 中启动的命令不会在新作业中启动,而是因为Xorg
它本身启动一个全新的会话(更不用说进程组)来附加该 tty2 终端。
因此,asXorg
已将其自身从进程组中删除,这样做kill %1
不会杀死它。
请注意,kill %1
向作业的进程组,而不是单个 pid。要将信号发送到进程组,您需要:
kill -- -7246
在我上面的例子中,这会杀死 pids 7246(bash 子 shell)和 7274(xeyes
),但不会杀死Xorg
(7247),因为它不在 7246 进程组中。