人们常说“&”将进程置于后台执行,但当终端关闭时该进程将被杀死。但据我所知,在我关闭终端后很长一段时间内,我发送到后台的所有内容都继续处于活动状态。例如:
$ tail -f /var/log/messages/ &
即使启动该进程的用户下没有其他进程,并且所有终端都早已消失,该进程仍将继续运行。这是为什么?
答案1
只是一个猜测(这是bash
具体的):文档对于huponexit
shell 选项说
如果设置,当交互式登录 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
.