为什么我的 shell 启动的后台作业比父 shell 和控制终端的生存时间更长?

为什么我的 shell 启动的后台作业比父 shell 和控制终端的生存时间更长?

人们常说“&”将进程置于后台执行,但当终端关闭时该进程将被杀死。但据我所知,在我关闭终端后很长一段时间内,我发送到后台的所有内容都继续处于活动状态。例如:

$ tail -f /var/log/messages/ &

即使启动该进程的用户下没有其他进程,并且所有终端都早已消失,该进程仍将继续运行。这是为什么?

答案1

只是一个猜测(这是bash具体的):文档对于huponexitshell 选项说

如果设置,当交互式登录 shell 退出时,Bash 将向所有作业发送 SIGHUP

在我的系统上,默认情况下似乎没有设置。您可以检查

shopt -p huponexit

如果输出包含-u,则未设置。

答案2

当一个进程需要终端进行输入或输出并发现它不存在时,使用“&”而不是 nohup 放在后台的进程将会终止。在这种情况下,tail当有东西写入 /var/log/messages 时,可能会退出,尽管可能存在一些缓冲区问题,会延迟它直到写入多条消息。

使用 启动进程./foo > /dev/null 2&1 < /dev/null大约相当于使用 nohup 启动。基本上,nohup 所做的就是负责重定向尚未从终端重定向的任何输入和输出。

答案3

& 符号&会将进程置于后台。文件描述符(stdout、stderr、stdin)不受影响。在 shell 退出时,shell 将发送SIGHUP到它生成的所有内容,因此当此 shell 关闭时,后台进程将接收SIGHUP并可能终止。在某些 shell(bash、zsh)中,您可以通过使用命令来阻止这种情况disown,该命令将告诉 shell 在 shell 关闭时不要发送它SIGHUP,并且进程将继续运行。

SIGSTOP您还可以通过发送(通常在终端中使用 Ctrl-Z)然后将进程置于后台 ( bg)来执行与“使用 & 符号置于后台”等效的操作。

nohup 的工作原理是忽略 SIGHUP。然后,该信号处理将传递给您运行的子进程。 nohup 还会检查 stdout 的去向,如果它去终端,它将 stdout 和 stderr 重定向到文件。信号处理更改以及可能的重定向后,它会在后台运行您的进程。

那么,有什么区别呢?

后台进程不会忽略SIGHUP,尽管您可以告诉您的 shell 不要以 disown 的方式发送它。除非被阻止,否则nohup将 stdout 重定向到 nohup.out 文件,这是我讨厌的,只要我需要删除随机散布在磁盘上的 nohup.out 文件。

还有setsid,它使您的进程成为进程组领导者。进程组领导者永远不会SIGHUP被任何 shell 发送给它。 setsid对 stdout/stderr 没有太多作用,我倾向于使用setsid而不是nohup.

相关内容