我如何派生一个没有退出外壳的进程?


31

如果我从外壳运行emacs:

$ emacs foo &

然后杀死该外壳,emacs死亡。

如何运行命令,以使该命令在Shell死后不会死?

我找到了对nohup的引用,但这似乎无济于事:

$ nohup emacs foo &

Shell死后仍可杀死emacs。

Answers:


13

您没有提及它是作为X应用程序运行还是作为控制台应用程序运行。

如果它是作为控制台应用程序,则当然需要关闭。您摆脱了它的输入/输出,更确切地说,摆脱了它所在的(伪)tty。这不太可能是您的意思,所以让我们假设您正在谈论X应用程序。

nohup应该可以工作,不确定为什么不可以。当外壳关闭时,它将发送SIGHUP到其进程组中的所有进程。nohup告诉命令忽略SIGHUP。

您也可以尝试使用setsid,它使流程与流程组断开连接

alias emacs='setsid emacs'

或在disown之后添加&


啊,伟大的setid作品。抱歉,不清楚。是的,我指的是实际上不在外壳中运行的X应用程序。基本上,我想从外壳启动emacs(或任何其他进程),但我不希望它与外壳捆绑在一起。为了方便起见,我只是从那里开始。
sligocki

41

最可靠的方法似乎是:

(setsid emacs &)

这用于( &)派生到后台,并setsid与控制tty分离。

您可以将其放在shell函数中:

fork() { (setsid "$@" &); }

fork emacs

可能是:

  • disown内建命令:

    emacs &
    disown $!
    

    &充当命令分隔符,并且disown默认为最新作业,因此可以缩短为:

    emacs & disown
    
  • fork()

    (emacs &)
    

    括号内的命令在( )单独的shell进程中运行。

  • setsid正如Rich所建议的那样,可能是最佳选择,因为它通过创建一个新的会话来取消流程的控制TTY :

    setsid emacs
    

    但是,这也有点不可预测-仅fork()当它是进程组的领导者时才会进入后台(例如,如果setsidsh脚本中使用,则不会发生;在这种情况下,它只会变得对Ctrl- C。)


大!这些都对我有用。很高兴在我的武器库中提供更多工具。
sligocki 2010年

嗯...行(exec emacs)吗?
Hello71 2011年

@Hello:这与just没什么不同(emacs)。如果给子外壳一个命令,exec则至少在情况下暗含bash。同样适用于bash -c 'foo'bash -c 'exec foo'。(但是,请注意emacs 本身可能正在与终端分离;例如gvim这样做。最好使用行为已知的程序进行测试。)
grawity 2011年

非常了解双叉技术;谢谢!
Dave Abrahams

在拖钓解决我自己的问题时发现了这个问题。(setsid emacs&)为我工作。感谢您的书面答复。
Paulb

5

检查您的外壳设置。您也可以尝试使用屏幕代替nohup


screen -r如果您Ctrl-A Ctrl-D在注销之前使用它来断开连接,屏幕允许您稍后重新进入该过程。
Broam 2012年

这是非常好的一点。我需要相反的操作,即派生一个子shell并执行其他任务,而不必等待其完成,但是screen -d -m sh -c "{do stuff } exit"这更有意义。
Nemo
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.