进一步阅读

进一步阅读

关于 nohup 有大量的堆栈交换答案,这里有几个供参考:
如果您已经使用“&”进行分叉,那么什么时候需要“nohup”?
为什么使用“nohup &”而不是“exec &”

规范的答案似乎是,使用 nohup 可以防止进程在终端关闭时结束,因此这样的命令:
nohup mycommand >& mycommand_output.txt &
下次登录时仍将运行,并且它会保存输出,以便我稍后可以检查。

但是,如果我保存一些击键:
mycommand >& mycommand_output.txt &
当我下次登录时,它仍然在运行。

它与 nohup 不同,因为我可以用 来停止它kill -HUP。当我重新登录时,ps -x显示进程的 TTY 为 now ?,因此该进程尚未连接到终端。

为什么当我退出 shell 时进程没有停止?
如果我不使用 nohup,我可以放心地假设我的进程不会结束吗?

以防万一,我当前的环境涉及从 Ubuntu 机器通过 SSH 连接到 Debian 机器。

答案1

为什么当我退出 shell 时进程没有停止?

可能是因为你告诉了 shelldisown它。或者您可能没有使用交互式作业控制 shell 作为会话引导进程。

世界在 20 世纪 80 年代确定的会话+进程组组合模型的工作原理如下:会议主持人过程。这就是从终端获取挂断信号的原因线路纪律当终端挂断时。预计它会放大该信号,本身将信号发送到它所产生的所有“作业”。交互的作业控制shell 可以做到这一点;大多数其他计划不希望承担会议主持人的职责,也不会。

当会话领导者将挂断信号发送给它们时,使用nohup使这些“作业”中的进程忽略挂断信号。使用disown会使会话领导者 shell 忘记某个作业,因此它从一开始就不会向其发送挂断信号。

如果我不使用 nohup,我可以放心地假设我的进程不会结束吗?

不。如果他们没有接受过disown教育,那么他们将要由会话领导者交互式作业控制 shell 进程发送挂断信号。

此外:systemd 的人们试图实现一种与内核会话等效的用户空间机制,但他们对此做了一些尝试,这给(某些)systemd 操作系统带来了进一步的复杂性。在 systemd 会话挂起时SIGHUP,它们不会像内核的线路规则那样仅发送给会话领导者,而是错误地发送SIGTERM全部过程,错误地表示关闭而不是挂断

SIGTERM对于所有进程来说,当然是在标准会话+进程组模型中,系统关闭时发生的情况;这会杀死所有进程,包括否认的进程和忽略挂断信号的进程。当然,它也会杀死既没有disown编辑也没有编辑的进程。nohup

进一步阅读

答案2

我可以放心地假设如果我不使用 nohup 我的进程就不会结束吗

不会。如果终端挂起并且它有一个交互式 shell 作为会话领导者,则该 shell 将收到 SIGHUP 并将其重新发送到尚未被拒绝的作业。

如果 shell 自愿退出,并且该huponexit选项打开,它将向其作业发送 SIGHUP。

如果 shell 自愿退出并且有已停止的自有作业,bash 将使用 SIGTERM 杀死它们(不确定这是否是标准行为)。

如果 shell 自愿退出并且有已停止的无主作业,则终端驱动程序将通过 SIGHUP 终止它们(这绝对是标准规定的)。

所以在各种情况下你仍然可能被 SIGHUP 杀死。

也就是说,通过查看 nohup 源代码http://src.gnu-darwin.org/src/usr.bin/nohup/nohup.c.html,它似乎在纯 shell 中或多或少可行:

nohup_sh()
(
    set -e
    if [ -t 1]; then
        exec >> nohup.out || exec >> "$HOME/nohup.out"
    fi
    if [ -t 0 ]; then
        exec 0</dev/null
    fi
    if [ -t 2 ]; then
        exec 2>&1
    fi
    trap '' HUP #ignore SIGHUP (inheritable)
    set -m || : #to prevent SIGINT and SIGQUIT from being ignored
    #(probably not needed, but the nohup binary won't ignore them, unlike
    # & without set -m)

    command "$@" &
)

您可能不需要 之外的额外内容trap '' HUP,尽管如果作业尝试写入断开连接的终端(这是重定向所阻止的),它会收到 SIGPIPE。

相关内容