什么确切地决定了后台作业是否在退出 shell 时被终止或被终止?

什么确切地决定了后台作业是否在退出 shell 时被终止或被终止?

这个问题已经出现相当 A 很多真的 很多),但我发现答案通常不完整。一般问题是“为什么我退出/终止 ssh 时我的作业会被终止/不会被终止?”,以下是我发现的答案。第一个问题是:以下信息有多普遍?以下内容似乎适用于现代 Debian Linux,但我遗漏了一些部分;其他人需要知道什么?

  1. 当 ssh 连接关闭时,所有子进程(无论是否在后台运行)都会被 SIGHUP 终止除非huponexit选项已设置:运行shopt huponexit以查看是否为真。

  2. 如果huponexit为真,则可以使用nohupdisown将进程与 shell 分离,这样退出时进程就不会被终止。或者,使用 运行screen

  3. 如果huponexit为假,则是默认的在当今的一些 Linux 上,后台任务将会不是在正常注销时被终止。

  4. 即使huponexit为假,如果 ssh 连接被杀或 退出(不同于正常注销),那么后台进程仍将被终止。这可以通过(2) 中的disown或来避免。nohup

  5. (a) 父进程是终端的进程和 (b) 具有 stdin、stdout 或 stderr 的进程之间存在一些区别已连接至终端我不知道当过程 (a) 和非 (b) 时会发生什么,反之亦然。

最后一个问题:我如何避免行为 (3)?换句话说,默认情况下,Debian 后台进程在注销后自行愉快地运行,但在 ssh 连接被终止后则不会。我希望无论连接是正常关闭还是被终止,进程都会发生同样的事情。或者,这是一个坏主意?

编辑:另一个重要的方法是让作业不被终止,无论哪种情况,它都是有效的 (?),就是让它们通过屏幕。但是,问题更多的是了解什么时候终止以及什么时候不终止:例如,有时人们希望在注销时终止作业。

更多主题:-关于信号 (sighup)、作业和控制终端的说明 -https://serverfault.com/questions/117152/do-background-processes-get-a-sighup-when-logging-off -关闭 SSH 时继续 SSH 后台任务/作业 -SSH 会话关闭后,后台运行的作业是否会继续运行? -防止关闭 SSH 客户端后停止正在运行的后台进程 -我如何通过 SSH 启动一个进程以便它在我断开连接后仍能继续运行? -无法在 OS X 上保持远程作业运行 -关闭 SSH 连接

答案1

进程不会被“用 SIGHUP 终止”——至少,严格意义上来说不是。相反,当连接断开时,终端的控制进程(在本例中为 Bash)会收到一个挂断信号*,通常缩写为“HUP 信号”,或简称为 SIGHUP。

现在,当进程收到信号时,它可以以任何方式处理它**。大多数信号(包括 HUP)的默认设置是立即退出。但是,程序可以自由地忽略信号,甚至运行某种信号处理函数。

Bash 选择最后一个选项。它的 HUP 信号处理程序检查“huponexit”选项是否为真,如果是,则向其每个子进程发送 SIGHUP。只有完成此操作后,Bash 才会退出。

同样,每个子进程在接收到信号时都可以自由地做任何它想做的事情:将其保留为默认值(即立即死亡)、忽略它或运行信号处理程序。

Nohup 只是将子进程的默认操作改为“忽略”。但是,一旦子进程运行,它就可以自由地改变自己对信号的响应。

我认为这就是为什么有些程序即使使用 nohup 运行也会死机的原因:

  1. Nohup 将默认操作设置为“忽略”。
  2. 程序在退出时需要进行某种清理,因此它会安装一个 SIGHUP 处理程序,顺便覆盖“忽略”标志。
  3. 当 SIGHUP 到达时,处理程序运行,清理程序的数据文件(或任何需要完成的操作)并退出程序。
  4. 用户不知道或不关心处理程序或清理,只是看到程序尽管有 nohup 但仍退出。

这就是“disown”的作用所在。无论 huponexit 选项是什么,Bash 已放弃的进程都不会收到 HUP 信号。因此,即使程序设置了自己的信号处理程序,信号也永远不会被发送,因此处理程序永远不会运行。但请注意,如果程序试图向已注销的用户显示一些文本,则会导致 I/O 错误,这可能会导致程序退出。

* 是的,在您询问之前,“挂断”术语是 UNIX 拨号大型机时代遗留下来的。

** 无论如何,大多数信号。例如,SIGKILL总是导致程序立即终止,就这样。

答案2

1-4 点是正确的。我对第 5 点一无所知。至于你的最后一点,一个很好的应用程序,屏幕,将允许您让所有进程运行至其自然结束,无论您如何终止连接。Screen 在存储库中。

screen 的说明不太容易阅读,但其中指出:

调用 screen 时,它会创建一个带有 shell(或指定命令)的窗口,然后不再打扰您,这样您就可以像平常一样使用该程序。然后,您可以随时创建新的(全屏)窗口,其中包含其他程序(包括更多 shell)、关闭现有窗口、查看窗口列表、打开和关闭输出日志记录、在窗口之间复制和粘贴文本、查看回滚历史记录、以任何您希望的方式在窗口之间切换等。所有窗口都完全独立地运行其程序。 当程序窗口当前不可见时,甚至当整个屏幕会话与用户终端分离时,程序仍会继续运行。当程序终止时,screen(默认)会关闭包含它的窗口。如果此窗口在前台,则显示切换到上一个窗口;如果没有剩余窗口,screen 将退出。

我已经强调了最重要的部分:您可以使用命令 Ctrl+a+d 分离窗口,然后您可以终止/注销您的会话,现在分离的窗口将继续存在,其中的程序仍在运行。当您重新连接时,例如通过启动新的 ssh 会话,命令屏幕-r将恢复先前分离的屏幕会话,并且所有输出到标准错误/输出都清晰可见。

相关内容