关闭终端窗口与终止/退出有何不同?

sud*_*dus 2 bash background-process

我正在尝试帮助 AskUbuntu 的用户解决以下问题,

退出终端与关闭终端

语境:-

我正在 bash 中运行一个进程,并&在后台模式下附加 ie。该进程有一个while(1)即它将永远运行。我的 bash 是父进程,我的进程是子进程。我想了解当父进程终止时内核如何处理子进程。

观察结果:-

  1. 如果我退出终端(使用exit终端命令),/lib/systemd/systemd --user则成为子进程的父进程
  2. kill如果我从另一个终端终止终端进程(使用),结果与上面相同
  3. 如果我使用十字图标关闭终端,子进程也会终止

问题:-

关闭与杀死/退出有何不同?

我已经写了一个答案,但觉得我不太明白发生了什么,我认为在 Unix & Linux 上提供帮助的几个人比我更了解并且可以解释发生了什么。

因此,请通过插入并写下答案来帮助我们理解(代替我在 AskUbuntu 上的尝试)。

小智 5

1 的答案是systemd --user采用孤儿(即扮演 pid 1 = init 的角色),因为它通过prctl(PR_SET_CHILD_SUBREAPER, 1)在生成其子级之前调用而成为“子收割者”。这是一个 Linux 扩展。

3 的答案是,这取决于终端仿真器。它们的工作方式并不相同。

但一般来说,1,2 和 3 之间的区别在于,在后一种情况下bash将收到一个SIGHUP信号 [1] 并将其重新发送给其子进程,从而导致后台进程死亡:

shell [即 bash] 在收到SIGHUP. 在退出之前,交互式shell 会重新 SIGHUP 向所有正在运行或已停止的作业发送 。发送停止的作业SIGCONT以确保它们收到 SIGHUP.

这是一个bash 扩展;并非所有 shell 都重新发送SIGHUP信号。具体来说,dash(/bin/shUbuntu 上的)不会做这样的事情。


SIGHUP但是,即使在 1 的情况下,如果后台进程在其进程组中有一个已停止的进程(使用 模拟终端模拟器script),它也可以获得信号:

$ script -q /dev/null -c /bin/bash
$ sh -c 'sleep 1 & kill -STOP $!; echo $$; while sleep 1; do :; done' &
[1] 3317
$ 3317

$ exit
exit
$ ps 3317
  PID TTY      STAT   TIME COMMAND
    # 3317 is dead.
Run Code Online (Sandbox Code Playgroud)

停止(不是睡眠的sleep进程已经关闭了它的父进程。如果你遗漏了这个sleep 1 & kill -STOP $!部分,它就会存活下来。

与前一个不同,这是操作系统的标准功能,而不是 bash 或其他 shell 特有的功能。

[1] bash 将收到一个SIGHUP信号,因为它位于前台进程组中,并且终端仿真器已经破坏了伪终端(导致内核发送 )SIGHUP或本身SIGHUP显式发送了 。