Subshel​​l 工作澄清

Subshel​​l 工作澄清

我运行命令(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, 7246for bash),但Xorg不是在该进程组中。

这不是因为&after Xorg,在子 shell 中启动的命令不会在新作业中启动,而是因为Xorg它本身启动一个全新的会话(更不用说进程组)来附加该 tty2 终端。

因此,asXorg已将其自身从进程组中删除,这样做kill %1不会杀死它。

请注意,kill %1向作业的进程组,而不是单个 pid。要将信号发送到进程组,您需要:

kill -- -7246

在我上面的例子中,这会杀死 pids 7246(bash 子 shell)和 7274(xeyes),但不会杀死Xorg(7247),因为它不在 7246 进程组中。

相关内容