异步Shell命令

131

我正在尝试使用Shell脚本启动一个命令。我不在意它何时完成,也不关心如何完成或者为什么完成。我想要进程启动并运行,但是我希望能够立即返回到我的Shell。


2
请参阅Unix和Linux Stack Exchange上的nohup,disown和&之间的区别 - jww
1
对于那些寻求更深入的答案,涉及nohup&disown之间的区别,请单击此处滚动到第四个答案 - noɥʇʎԀʎzɐɹƆ
5个回答

143
你可以在后台运行该脚本:
$ myscript &
请注意,这与将 & 放在您的脚本中是不同的,后者可能不会产生您期望的效果。

1
我知道这会是件很简单的事情,非常感谢... Linux不是我的强项,但我正在努力迎头赶上... 顺便问一下,如果与nohup结合使用,这个能正常工作吗? - LorenVS
4
在命令行中使用"&"和在脚本中使用有何不同?我不知道它们之间有区别。 - Jacob Sharf
11
试试看就知道了。如果&符号在脚本内部,并且没有wait命令,那么当脚本退出时,后台命令将被终止。 - Carl Norum
1
哦,这解释了很多问题。我最近注意到了一些可能由此引起的影响。通过谷歌搜索,我找到了这个页面。谢谢。 - Jacob Sharf
如果 myscript 修改终端环境,例如它是一个终端初始化命令,不需要立即执行并且可以延迟执行,那么它是否仍会修改终端环境? - noɥʇʎԀʎzɐɹƆ
在编程中,“后台运行”的意思是内核的默认行为是同步的。如果我们想要将其更改为异步,则使用“&”,这使命令以异步(并行)方式运行(这就是为什么它看起来像在后台运行)。 - Abhijit Manepatil

97

大家似乎都忘了disown命令,这里是一个总结:

  • &将作业置于后台。

    • 使其在尝试读取输入时阻塞,
    • 使shell不等待其完成。
  • disown从shell的作业控制中移除进程,但仍将其连接到终端。

    • 其中之一的结果是shell不会向该进程发送SIGHUP(如果shell接收到SIGHUP,它也会向该进程发送SIGHUP,这通常会导致该进程终止)。
    • 显然,它只能应用于后台作业(因为在前台作业运行时无法输入它)。
  • nohup断开进程与终端的连接,重定向其输出到nohup.out并保护它免受SIGHUP的干扰。

    • 该进程不会接收任何发送的SIGHUP
    • 它完全独立于作业控制,原则上也可以用于前台作业(虽然这不是非常有用)。
    • 通常与&一起使用(作为后台作业)。

disown命令和在OSX上的用法 - Ani Menon
9
这是最好的答案。最全面的。 - noɥʇʎԀʎzɐɹƆ
4
当然是最好的答案,不知道为什么点赞数这么少。 - HeberLZ
我仍然有疑问。如果使用 nohup 运行命令,例如 nohup my-script.sh > out 2>&1 &,是否需要调用 disown - Vlad Ganshin
2
@VladGanshin 不。 - Ani Menon
显示剩余3条评论

58
nohup cmd

关闭终端不会中止程序,输出默认保存在 nohup.out 文件中。

你可以将此与后台运行组合使用,

nohup cmd &

并且摆脱输出

nohup cmd > /dev/null 2>&1 &

你也可以使用disown命令。输入cmdCtrl-Zbgdisown即可。


2
很酷,一切都如此奇妙地结合在一起。我想最初可能会让我感到困惑的是顺序,但我想你可以只记住它(你写的或“nohup cmd &> /dev/null 2>&1” :))。 - LorenVS
今晚我偶然发现了这个。我已经和一个 shell 脚本斗争了两天,而这个建议让事情开始工作了。非常感谢! - JD Long
太棒了,这非常有用。当在后台模式下运行时,您可以使用“tail nohup.out”每隔一段时间检查命令的输出,这将显示命令输出的最后10行。我用它来进行rsync备份作业,以了解当前正在处理哪个文件。 - Martin Hansen
如果我这样做,但想停止后台进程怎么办? - Stephan Bijzitter
Shell会在你启动一个作业时打印一个作业标识符,就是为了这个目的。你可以随时用jobs命令查看正在运行的作业。 - tripleee
将输出丢弃是个不好的主意。把它发送到文件中,这样你就可以看到它在做什么,并对任何错误信息做出反应。 - tripleee

29

另外,当您运行程序后,可以按Ctrl-Z停止您的程序,然后输入

bg

将您上次停止的程序放入后台。(如果您启动了某些内容但没有使用'&',并且仍希望将其放入后台而不必重新启动,则此方法很有用)


3
谢谢,那是个很酷的小技巧...我开始真正欣赏一些Shell的好处了... - LorenVS

8

screen -m -d $command$ 命令可以在一个分离的会话中启动某个命令。你可以使用 screen -r 命令来附加到已经启动的会话。这是一个非常好用的工具,对于远程会话也非常有用。更多信息请参考 man screen


@LadenkovVladislav 我有95%的把握你可以在RedHat上安装screen。我已经在CentOS上安装过了。 - BuvinJ
在Ubuntu上,我想仿效Windows / Batch中的“start”命令。即异步启动前台(GUI)程序,并通过shell脚本继续进行。 这正是这样做的方法。 - BuvinJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接