我运行该命令(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 的子进程?这里发生了什么,我做错了什么?
除了告诉我该怎么做之外,将不胜感激对这里到底发生了什么的深入解释。
如果您想观察作业控制,您需要使用将列出进程组 ID 和会话 ID的
-j
选项。ps
在这里,我看到:
你看
Xorg
是一个孩子,xeyes
因为我的 shell 比子shell 的进程更优化bash
并xeyes
在子 shell 的进程中运行,因为它是子 shell 的最后一个命令。不,一个子shell在它终止时不会杀死它的孩子,这会使shell无法使用(这里很明显它不能因为子shell已被替换xeyes
)。同样在
bash
:有一个额外的无用
bash
进程,只是等待xeyes
终止,之后不会做任何事情,否则与中相同zsh
,您看到shell创建了一个新进程组(6825 forzsh
,7246
forbash
),但Xorg
不是在那个进程组中。这不是因为
&
afterXorg
,在子shell中启动的命令不会在新作业中启动,这是因为Xorg
它本身启动了一个全新的会话(更不用说进程组)来附加该 tty2 终端。因此,
Xorg
从进程组中删除了自己,这样做kill %1
不会杀死它。请注意,
kill %1
将 SIGTERM 信号发送到作业的进程组,而不是单个 pid。要将信号发送到您需要的进程组:在我上面的例子中,它会杀死 pids 7246(bash 子shell)和 7274(
xeyes
),但不会杀死Xorg
(7247),因为它不在 7246 进程组中。