如何运行将在终端关闭后继续运行的命令?


313

有时我想开始一个过程而忘记它。如果我从命令行启动它,像这样:

redshift

我无法关闭终端,否则它将终止该过程。我可以以不中断进程就可以关闭终端的方式运行命令吗?


4
不是所有发行版上的默认安装,但屏幕是您的朋友:en.wikipedia.org/wiki/GNU_Screen
Zayne S Halsall 2010年

对于面临相同问题的任何人:请记住,即使您键入yourExecutable &并且输出不断出现在屏幕上,并且Ctrl+C似乎没有停止任何操作,即使屏幕正在滚动显示输出,您也只能盲目地键入disown;并按一下Enter,而您看不到什么您正在输入。该过程将被取消,您将可以关闭终端而该过程不会终止。
2016年

您可以使用屏幕多路复用器,例如tmux。可以通过ubuntu机器上的apt-get来获得
Himanshu,2016年

Answers:


311

以下2项之一应该起作用:

$ nohup redshift &

要么

$ redshift &
$ disown

有关其工作原理的更多信息,请参见以下内容:


5
第二个(redshift & disown)在Ubuntu 10.10上为我工作。将其全部放在一行上似乎工作正常。有什么理由我不应该这样做吗?
马修2010年

4
@Matthew第一个也应该工作正常,只是不像第二个那样背景(您可能希望nohup redshift &这样做也有背景)。将第二行放在一行上很好,尽管通常您用;redshift &; disown)分隔
Michael Mrozek

10
@Michael:;和和&都是命令分隔符,并且具有相同的优先级。唯一的区别是分别是同步执行还是异步执行。不需要&;优先使用&而已(它可以工作,但是有点多余)。
克里斯·约翰森

4
好的答案,可能还要补充一点,重定向stdout和stderr是个好主意,这样终端就不会被调试输出垃圾邮件了
Kim,2010年

12
另外,redshift &!将立即取消redshift。

143

如果您的程序已经在运行,则可以使用暂停它Ctrl-Z,然后使用将其拖入背景,bg然后将其拉入后台disown,如下所示:

$ sleep 1000
^Z
[1]+  Stopped                 sleep 1000
$ bg
$ disown
$ exit

3
断开后,如何再次读取运行过程的标准输出?
Necktwi 2014年

2
@ neckTwi,serverfault.com
Stefan

1
由于某些原因,这对我不起作用(centos)
Ian

此过程后如何终止进程?
达克(Palak Darji)'16年

2
@necktwi disown不会断开stdout或stderr的连接。但是nohup>/dev/null(断开标准输出),2>/dev/null(断开标准错误)也是如此。它(disown)断开作业控制。
ctrl-alt-

45

@StevenD已经发布了很好的答案,但是我认为这可能会进一步澄清它。

该进程在终端终止时被终止的原因是,您启动的进程是该终端的子进程。一旦关闭终端,这也会杀死这些子进程。您可以使用来查看进程树pstree,例如kate &在Konsole中运行时:

init-+
     ├─konsole─┬─bash─┬─kate───2*[{kate}]
     │         │      └─pstree
     │         └─2*[{konsole}]

要使kate进程与konsole终止时分离,请与命令一起konsole使用nohup,如下所示:

nohup kate &

关闭后konsolepstree将如下所示:

init-+
     |-kate---2*[{kate}]

kate将生存。:)

一个替代方案是使用screen/ tmux/ byobu,其将保持壳运行,独立于终端的。


我在使用disown方法时遇到了问题。目前,这对我有用,因此很赞。我也喜欢这样,因为我可以拖尾-f nohup.out看看发生了什么,但不必担心我的会话失败
Ian

27

您可以在终端中运行这样的过程

setsid process

这将在新会话中运行程序。如http://hanoo.org/index.php?article=run-program-in-new-session-linux中所述


1
您认为setid优于nohup有什么优势?
itsbruce 2012年

1
1)它不会显示有关的烦人消息nohup.out。2)它不会保留在Shell的作业列表中,因此不会使输出混乱jobs
Mikel,2012年

这是唯一适用于在lxterminal中运行,启动pcmanfm并退出的脚本的解决方案(使用setid时,终端可以在pcmanfm继续运行时关闭)。非常感谢!
desgua

9

尽管所有建议都可以正常工作,但我发现我的替代方法是使用screen,该程序可在屏幕上设置虚拟终端。

您可以考虑以开头。屏幕几乎可以安装在所有Linux和Unix派生产品上。点击+ 和(小写)将开始第二个会话。这将允许你通过点击来来回切换初始会话之间+ 和或较新的会话击中+ 和。一个终端最多可以有十个会话。我曾经在工作中开始一个会话,回家,在我的工作机中使用ssh,然后调用。这将使您重新连接到该远程会话。screen -S session_nameCtrlACCtrlA0CtrlA1screen -d -R session_name


screen -d -m command:已分离屏幕内将开始它 ~# screen -d -m top ~# screen -ls There is a screen on: 10803..Server-station (Detached) 1 Socket in /root/.screen. ~# screen -x ....你的是,
亚历山大博士

7

仅通过shell即可完成所有操作的方法是关闭stdin并后台执行命令:

command <&- & 

这样,当您退出外壳程序时,它就不会退出。重定向标准输出是一个很好的可选操作。

缺点是事实之后您不能执行此操作。


我在ubuntu中尝试过。杀戮终端也关闭了启动进程。知道为什么会这样吗?
Ashok Koyi

7

我有一个脚本可以:

  • 在后台运行任意命令

  • 阻止它们被终端窗口杀死

  • 禁止输出

  • 处理退出状态

我用它主要为geditevinceinkscape等所有有很多烦人的终端输出的。如果命令之前完成TIMEOUT,则返回nohup的退出状态,而不是零。

#!/bin/bash

TIMEOUT=0.1

#use nohup to run the command, suppressing its output and allowing the terminal to be closed
#also send nohup's output to /dev/null, supressing nohup.out
#run nohup in the background so this script doesn't block
nohup "${@}" >/dev/null 2>&1 &
NOHUP_PID=$!

#kill this script after a short time, exiting with success status - command is still running
#this is needed as there is no timeout argument for `wait` below
MY_PID=$$
trap "exit 0" SIGINT SIGTERM
sleep $TIMEOUT && kill $MY_PID 2>/dev/null & #ignore "No such process" error if this exits normally

#if the command finishes before the above timeout, everything may be just fine or there could have been an error
wait $NOHUP_PID
NOHUP_STATUS=$?
#print an error if there was any. most commonly, there was a typo in the command
[ $NOHUP_STATUS != 0 ] && echo "Error ${@}"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

例子...

>>> run true && echo success || echo fail
success
>>> run false && echo success || echo fail
Error false
fail
>>> run sleep 1000 && echo success || echo fail
success
>>> run notfound && echo success || echo fail
Error notfound
fail

6

我更喜欢:

(应用名称 &)

例如: linux@linux-desktop:~$ (chromium-browser &)

键入命令时,请确保使用括号!


1
关闭终端将终止进程,而这正是OP(和我,因此来到这里)想要避免的过程
gromit190 '16

可能您有我在答案中使用的没有括号的提示命令,如果这样关闭终端将终止该过程,否则将不会发生。我已经编辑了上面的解决方案以使其更加清楚。
daGo

为我工作,tnx
noadev

我想知道为什么没有更多的支持。nohup防止任何tty输出,而我实际上只想将输出重定向到文件,并且这样做可以防止,所以这对我来说是更好的解决方案。
redanimalwar

4

您可以将进程(PID)设置为在注销并关闭终端会话后不接收HUP信号。使用以下命令:

nohup -p PID

3

可以说与apolinsky提供答案类似,我在上使用了一个变体screen。香草命令是这样的

screen bash -c 'long_running_command_here; echo; read -p "ALL DONE:"'

Ctrl ACtrl D在简单的情况下,可以使用断开会话的连接并重新连接screen -r。我有这个裹在一个叫做脚本session的是住在我PATH准备方便:

#!/bin/bash
#
if screen -ls | awk '$1 ~ /^[1-9][0-9]*\.'"$1"'/' >/dev/null
then
    echo "WARNING: session is already running (reattach with 'screen -r $1')" >&2
else
    exec screen -S "$1" bash -c "$@; echo; echo '--------------------'; read -p 'ALL DONE (Enter to exit):'"
    echo "ERROR: 'screen' is not installed on this system" >&2
fi
exit 1

仅当您事先知道要断开程序时,此方法才有效。它不提供要断开已运行的程序的功能。


2

与以前发布的其他答案类似,由于reptyr,可以转移一个正在运行的进程以追溯使用“屏幕” ,然后关闭终端。在这篇文章中描述了这些步骤。采取的步骤是:

  1. 暂停流程
  2. 在后台恢复过程
  3. 取消流程
  4. 启动屏幕会话
  5. 查找过程的PID
  6. 使用reptyr接管流程
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.