我读了一个声称正在运行的用户的答案
foo 2>&1 >& output.log &
Run Code Online (Sandbox Code Playgroud)
foo
即使他们注销,也会导致继续运行。据该用户称,这甚至可以通过 SSH 连接工作。
我并不真正相信这一点,因为我的印象是,在与 SSH 断开连接或终止 TTY 的情况下,shell 及其进程会收到 SIGHUP,导致它们终止。这一点,我的假设下,被使用的唯一理由nohup
在这样的情况下,或者tmux
,screen
等。
然后我查看了glibc 的手册:
该信号还用于向与该会话相关联的作业报告终端上控制进程的终止;此终止有效地断开会话中的所有进程与控制终端的连接。
这似乎证实了我的想法。但进一步看,它说:
如果进程是具有控制终端的会话领导者,则向前台作业中的每个进程发送 SIGHUP 信号,并且控制终端与该会话解除关联。
那么,这是否意味着置于后台的作业将不会收到 SIGHUP?
令我更加困惑的是,我运行了一个交互式 Zsh 会话,运行yes >& /dev/null &
并输入了exit
,当 Zsh 警告我有正在运行的作业时,exit
第二次输入后,它告诉我它已经 SIGHUPed 一个作业。在 Bash 中执行完全相同的操作会使工作继续运行……
当我们说一个进程有一个控制终端时,我们的意思是该进程本身有一个控制终端,还是该进程所属的会话有一个控制终端?
我曾经认为它是具有控制终端的会话,但后来我阅读了以下内容(从这里),这意味着它是具有控制终端的进程:
进程的属性之一是其控制终端。使用 fork 创建的子进程从其父进程继承控制终端。这样,一个会话中的所有进程都从会话领导者那里继承了控制终端。控制终端的会话领导者称为该终端的控制进程。