nohup,disown和&之间的区别


579

之间有什么区别

$ nohup foo

$ foo &

$ foo & 
$ disown

50
等待,您可以在不指定PID的情况下放弃?大!
ripper234

34
还有foo &!等于等于从一开始就将其丢弃的功能。
user4514 2012年

26
Bash不支持&!。
乔纳斯·康斯伦德

20
foo & disown立即取消。
ctrl-alt-delor 2016年

9
我很乐意看到的一提setsid,它如何与disownnohup
YoungFrog

Answers:


558

首先,让我们看一下如果从交互式外壳程序(连接到终端)启动程序而没有&(并且没有任何重定向)启动程序会发生什么情况。因此,假设您刚刚输入了foo

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

现在,让我们看看如果将流程放在后台,即键入foo &

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

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

什么nohup呢,在另一方面,是有效地处理从所述终端分开:

  • 它关闭标准输入(该程序即使在前台运行也将无法读取任何输入。它不会暂停,但会收到错误代码或EOF)。
  • 它将标准输出和标准错误重定向到文件nohup.out,因此,如果终端发生故障,则程序不会因写入标准输出而失败,因此不会丢失任何过程写入的内容。
  • 它防止进程接收到SIGHUP(因此名称)。

请注意,nohup不会从外壳程序的作业控件中删除该进程,也不会将其置于后台(但是由于前台nohup作业或多或少没有用处,因此通常使用来将其放入后台&)。例如,与之不同disown,shell仍会告诉您nohup作业何时完成(当然,除非shell在此之前终止)。

总结一下:

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

8
+1谢谢。然后一起使用disown,nohup和&会发生什么?
蒂姆(Tim)

15
如果同时使用这三个功能,则该过程在后台运行,已从Shell的作业控件中删除,并已与终端有效断开连接。
celtschk 2015年


1
disown %1和之间有什么区别disown -h %1?第二个将保留为常规作业(但忽略HUP信号),直到终端退出?
schemacs 2015年

4
也许值得包括(foo&)subshel​​l
jiggunjer,2016年

169

使用&会导致程序在后台运行,因此您将获得一个新的shell提示,而不是阻塞直到程序结束。nohupdisown基本上是无关; 它们抑制SIGHUP(挂断)信号,因此在关闭控制终端时不会自动终止程序。nohup作业首次开始时执行此操作。如果您nohup在开始工作时没有工作,则可以使用它disown来修改正在运行的工作。不带参数的情况下,它会修改当前作业,这是刚刚被后台处理的作业


10
nohup和disown之间的细微差别:disown命令会将其从作业列表中删除;Nohup不会。
Shawn J. Goff 2010年

191
nohup并且disown两者都可以说是抑制SIGHUP,但以不同的方式。nohup使程序最初忽略信号(程序可能会对此进行更改)。nohup还尝试安排程序不具有控制终端,以便SIGHUP在终端关闭时不会由内核发送该程序。disown完全在外壳内部;它导致外壳SIGHUP终止时不发送。
吉尔斯(Gilles)2010年

27
@Gilles,您的评论值得一个答案。
lesmana

5
只是对@ ShawnJ.Goff的有关disown从作业列表中删除作业的注释的说明。如果您未指定选项,则会将其从作业列表中删除。但是,如果指定该-h选项,则不会从表中删除每个jobspec 。相反,它使得它SIGHUP在shell收到时不会发送到作业SIGHUP
tacotuesday

4
只是为了澄清,使用&不给你一个终端,它分离stdin从过程并使其在后台运行,但两者stdoutstderr仍连接到当前终端。这意味着您可能会混合使用来自不同程序的文本,如果这样做的话会很烦人,gimp &并在尝试将tty用于其他操作时出现很多GTK +错误。
2014年

8

这是我的经验,试图在执行非终止命令(例如tail)后在后台运行办公室。对于本示例,我将使用sleep 100

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

看到办公室日志 /通过按Ctrl- C办公室停止

nohup ..&

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

看不到办公室日志 /按Ctrl- C办公室停止

和放弃

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

看到办公室日志 /通过按Ctrl- C办公室停止

setid ..&

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

看到了办公室日志 /通过按Ctrl- C办公室不停止

为了节省空间:
nohup setsid ..:不显示日志/ soffice 不会停止对Ctrl-C
nohup& disown底:不显示日志/ soffice停在Ctrl-C


2
我感谢提及setid并显示在特定情况下会发生什么的工作,但我希望看到更彻底的答案。尤其是每种解决方案的区别和相似之处,既可见(在关闭外壳或终端时会发生什么,输出将到达何处……),又是不可见的(在幕后做事及其含义)。公认的答案是一个很好的基础。
YoungFrog

1
@YoungFrog我会同意这一点!
Marinos

对我来说,nohup ⟨command⟩ & disown创建过程不会停止Ctrl+C
k.stm

@ k.stm您尝试了soffice吗?soffice命令似乎有所不同。因此,我考虑将其作为规则例外添加到此处。例如,当使用:时nohup .. &Ctrl-c正常按下不会导致命令停止,但会停止soffice。我等到有人加油并解释为什么要用办公室时才发生:)
Marinos

@MarinosAn是的,我做到了。我奔跑着nohup soffice &压了一下Ctrl+C。没有发生任何意外。
k.stm
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.