nohup、disown 和 & 之间的区别

nohup、disown 和 & 之间的区别

两者有什么区别

$ nohup foo

$ foo &

$ foo & 
$ disown

答案1

让我们首先看看如果从交互式 shell(连接到终端)启动程序而没有&(并且没有任何重定向)会发生什么。所以我们假设您刚刚输入foo

  • 正在运行的进程foo已创建。
  • 该进程从 shell 继承 stdin、stdout 和 stderr。因此它也连接到同一终端。
  • 如果 shell 收到 a SIGHUP,它还会SIGHUP向进程发送 a (这通常会导致进程终止)。
  • 否则,shell 将等待(被阻止),直到进程终止或停止。

现在,让我们看看如果将进程放在后台会发生什么,即输入foo &

  • 正在运行的进程foo已创建。
  • 该进程从 shell 继承 stdout/stderr (因此它仍然写入终端)。
  • 该进程原则上也继承了 stdin,但一旦它尝试从 stdin 读取,它就会停止。
  • 它被放入 shell 管理的后台作业列表中,这尤其意味着:
    • 它列出jobs并可以使用%n(其中n是作业编号)进行访问。
    • 可以使用将其转换为前台作业fg,在这种情况下,它会继续,就像您不会使用&它一样(如果它由于尝试从标准输入读取而停止,那么它现在可以继续从终端读取)。
    • 如果 shell 收到一个SIGHUP,它也会SIGHUP向进程发送一个 。根据 shell 以及可能为 shell 设置的选项,当终止 shell 时,它也会SIGHUP向进程发送 a 。

现在disown从 shell 的作业列表中删除该作业,因此上面的所有子点不再适用(包括SIGHUPshell 发送的进程)。但请注意,它仍然连接到终端,因此如果终端被破坏(如果它是一个 pty,则可能发生这种情况,如由xterm或创建的 pty ssh,并且控制程序通过关闭 xterm 或终止SSH连接),程序一旦尝试从标准输入读取或写入标准输出就会失败。

另一方面nohup,有效地将进程与终端分开:

  • 它关闭标准输入(程序将不是能够读取任何输入,即使它在前台运行。它不会停止,但会收到错误代码或EOF)。
  • 它将标准输出和标准错误重定向到文件nohup.out,因此如果终端出现故障,程序不会因写入标准输出而失败,因此进程写入的任何内容都不会丢失。
  • 它阻止进程接收 a SIGHUP(因此得名)。

请注意,确实nohup如此不是从 shell 的作业控制中删除该进程,并且也不将其放入后台(但由于前台nohup作业或多或少是无用的,因此您通常会使用 将其放入后台&)。例如,与 with 不同disown,shell 仍会告诉您 nohup 作业何时完成(当然,除非 shell 之前已终止)。

总结一下:

  • &将作业置于后台,也就是说,使其在尝试读取输入时被阻止,并使 shell 不等待其完成。
  • disown将进程从 shell 的作业控制中删除,但仍保持与终端的连接。结果之一是 shell 不会向其发送SIGHUP.显然,它只能应用于后台作业,因为当前台作业运行时你无法输入它。
  • nohup断开进程与终端的连接,将其输出重定向到nohup.out并屏蔽它SIGHUP。影响之一(命名的影响)是进程不会接收任何发送的SIGHUP.它完全独立于作业控制,原则上也可以用于前台作业(尽管这不是很有用)。

答案2

使用&会使程序在后台运行,因此您将得到一个新的 shell 提示符,而不是阻塞直到程序结束。nohup并且disown基本上不相关;它们抑制 SIGHUP(挂断)信号,因此当控制终端关闭时程序不会自动终止。nohup当工作第一次开始时执行此操作。如果您nohup在作业开始时没有启动,您可以使用disown修改正在运行的作业;没有任何参数,它会修改当前的作业,即刚刚后台运行的作业

答案3

这是我尝试在后台运行 soffice 的经验,遵循非终止命令(例如tail)。对于这个例子,我将使用sleep 100.

在下面的所有情况下,我都是这样执行的:

./scriptfile
<Ctl-C>

&

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

办公室日志/ 按Ctrl-C办公站

诺哈普..&

#!/bin/bash
nohup /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

没看到办公室日志/ 按Ctrl- Csoffice 停止

& 否认

#!/bin/bash
/opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard & disown
sleep 100

办公室日志/ 按Ctrl-C办公站

集西德..&

#!/bin/bash
setsid /opt/libreoffice4.4/program/soffice -invisible -nofirststartwizard &
sleep 100

办公室日志/ 按Ctrl- Csoffice不停歇

为了节省空间::
nohup setsid ..不显示日志/soffice不会停止Ctrl-C
nohup结尾处& disown:不显示日志/办公室停止于Ctrl-C

答案4

另请参阅daemonize(1) 实用程序,它处理有关运行“真正后台”进程的所有杂务。根据其文档:

daemonize 作为 Unix 守护进程运行命令。正如 W. Richard Stevens 在 1990 年出版的《Unix 网络编程》一书中所定义的那样(Addison-Wesley,1990),守护进程是“一个在后台执行的进程(即,没有关联的终端或登录 shell),或者等待某个进程”。事件发生,或等待定期执行某些指定的任务。”启动时,典型的守护程序将:

  • 关闭所有打开的文件描述符(特别是标准输入、标准输出和标准错误)
  • 将其工作目录更改为根文件系统,以确保它不会占用另一个文件系统并防止其被卸载
  • 重置其 umask 值
  • 在后台运行(即fork)
  • 与其进程组(通常是 shell)解除关联,以将自身与发送到进程组的信号(例如 HUP)隔离
  • 忽略所有终端 I/O 信号
  • 与控制终端断开连接(并采取措施不再重新获取控制终端)
  • 处理任何 SIGCLD 信号

大多数设计为作为守护进程运行的程序都可以自行工作。但是,您偶尔会遇到不这样做的情况。当您必须运行一个无法正确地将自己变成真正的 Unix 守护程序的守护程序时,您可以使用 daemonize 强制它作为真正的守护程序运行。

它取代了所有的&//混乱。nohupdisown

相关内容