如何完全从终端分离流程?


304

我在Ubuntu上使用Tilda(下拉终端)作为我的“命令中心”,这几乎是其他人使用GNOME Do,Quicksilver或Launchy的方式。

但是,我在努力从启动该终端的终端中完全分离一个过程(例如Firefox),即防止此类(非)子进程

  • 关闭始发终端时终止
  • 通过STDOUT / STDERR“污染”始发终端

例如,为了在“适当的”终端窗口中启动Vim,我尝试了一个简单的脚本,如下所示:

exec gnome-terminal -e "vim $@" &> /dev/null &

但是,这仍然会造成污染(此外,传递文件名似乎也不起作用)。


1
这也是一个好问题。我认为考虑Bash是一种编程语言是很公平的-尽管确实这个问题的范围可能更多地是在sysadmin方面……


Dup

您的用例本身并不描述完全分离。
jiggunjer

Answers:


344

首先; 一旦启动了流程,就可以通过先使其停止(命中Ctrl- Z),然后键入bg使其在后台继续运行来使其成为后台。它现在是一个“工作”,而其stdout/ stderr/ stdin仍然连接到你的终端。

您可以通过在其末尾添加“&”来立即启动一个后台进程:

firefox &

要在静默的背景下运行它,请使用以下命令:

firefox </dev/null &>/dev/null &

一些其他信息:

nohup是一个程序,您可以使用它来运行您的应用程序,以便可以将其stdout / stderr发送到文件中,并且关闭父脚本不会导致子级升高。但是,在启动应用程序之前,您需要具有先见之明才能使用它。由于工作方式的原因nohup,您不能仅将其应用于正在运行的进程

disown是一个bash内置函数,它从shell的作业列表中删除了一个shell作业。这基本上意味着您不能再使用fgbg但是更重要的是,当您关闭外壳时,外壳将不再挂起或发送SIGHUP给该孩子。不像nohupdisown使用的进程已经启动,中背景。

无法做的是在启动进程后更改其stdout / stderr / stdin。至少不是来自外壳。如果启动进程并告诉它其stdout是您的终端(默认情况下就是您要做的事情),则该进程将配置为输出到您的终端。您的外壳与流程的FD设置无关,这完全是流程本身管理的事情。进程本身可以决定是否关闭其stdout / stderr / stdin,但是您不能使用shell强制这样做。

要管理后台进程的输出,您可以从脚本中选择很多选项,“ nohup”可能是第一个想到的选项。但是对于交互过程,您开始却忘了静音(firefox < /dev/null &>/dev/null &),实际上您不能做很多事情。

我建议您使用GNU screen。使用screen,您可以在进程输出变得麻烦时关闭运行中的shell,然后打开一个新的shell ^Ac


哦,顺便说一句,不要$@在使用的地方使用“ ”。

$@意味着$1$2$3...,这将打开你的命令到:

gnome-terminal -e "vim $1" "$2" "$3" ...

那可能不是您想要的,因为-e只接受一个参数。使用$1表明你的脚本只能处理一个参数。

要使多个参数在您给定的情况下(带有gnome-terminal -e)确实很难工作,因为-e仅接受一个参数,这是一个shell命令字符串。您必须将参数编码为一个。最好,最可靠但很笨拙的方式是这样的:

gnome-terminal -e "vim $(printf "%q " "$@")"

非常感谢!可悲的是,我只能接受一个答案。我最后遇到了“ nohup $ @&> / dev / null&”和“ alias wvim ='launch.sh gnome-terminal -x vim'”

20
多么奇妙的详细信息。+1
Teekin 2011年

1
@ Hi-Angel当您关闭交互式bash shell时,bash HUP会激活所有活动作业。当您使用^ Z和bg进行处理时,它仍然是一项工作,但它是一项后台工作。要将其作为一项工作删除,请使用disown,然后关闭shell后该过程将继续进行,因为bash不再对其进行处理。
2014年

3
不会使用$*而不是$@解决单独字符串的问题吗?
sjas 2015年

2
您无法做的是在启动进程后更改其stdout / stderr / stdin。-不完全正确。使用reptyr此。
Stefan Seidel

198
nohup cmd &

nohup 完全分离过程(守护进程)


5
尽管简洁很有价值,但完整性更有价值。尽管nohup是GNU coreutil,但这里仅提供bash答案(或注意没有答案)是合适的。尽管如此,好的答案。
有限赎罪者

23
nohup只是忽略了SIGHUP信号。它正常执行该过程。没有守护进程。
nemo

1
@nemo这意味着该进程未分离,但是init如果shell退出,该过程将分离(和的子进程),对吗?
Noldorin

@Noldorin是的。忽略在外壳终止时发送的SIGHUP,将使子进程处于运行状态并被重新定位到init。
nemo

@nemo nohup也会使标准输入/输出静音。跟进disown,使其完全脱离。
jiggunjer

60

如果您正在使用bash,请尝试;参见bash(1)disown [jobspec]

您可以尝试的另一种方法是at now。如果您不是超级用户,则使用权限at可能会受到限制。


“ disown”似乎不是内部bash命令(在我的机器上不可用,我使用bash)。正如Ben所建议的,“ nohup”可能是一种更好(和标准)的方式。

1
从来没有想过使用“ at”,谢谢这个主意!
cadrian 2012年

1
at将执行委托给其他人,我喜欢!+1
Ninsuo

1
作为参考,这也适用zsh
编码器

1
此外,disown似乎还没有达到预期的效果gnome-terminal- disown终端退出时,ed进程仍然被杀死。我想知道为什么/如何。
凯尔·斯特兰德

38

阅读这些答案,我最初的印象是发行nohup <command> &就足够了。我在gnome-terminal中运行zsh时,发现nohup <command> &并没有阻止我的shell在退出时杀死子进程。尽管nohup这很有用,尤其是对于非交互式外壳,但只有在子进程不重置其SIGHUP信号处理程序时,它才能保证这种行为。

就我而言,nohup应该阻止挂断信号到达应用程序,但是子应用程序(在这种情况下为VMWare Player)正在重置其SIGHUP处理程序。结果,当终端仿真器退出时,它仍然可能杀死您的子进程。据我所知,这只能通过确保从Shell的Jobs表中删除该过程来解决。如果nohup用内置的shell覆盖(有时是这种情况),那么这可能就足够了,但是如果不是这样的话...


disown由shell内建在bashzshksh93

<command> &
disown

要么

<command> &; disown

如果您喜欢单线。这通常具有从作业表中删除子流程的效果。这样,您就可以退出终端仿真器,而不会完全无意间通知子进程。无论SIGHUP处理程序是什么样子,都不应杀死您的子进程。

取消操作后,该进程仍然是终端仿真器的子级(pstree如果您想观看实际操作,请继续使用该子进程),但是在终端仿真器退出后,您应该看到它已附加到init进程中。换句话说,一切都应该是应有的,并且应该是您想要的。

如果您的外壳不支持disown怎么办?我强烈建议您切换到可以的功能,但是如果没有该选项,您将有几种选择。

  1. screen并且tmux可以解决此问题,但是它们的重量要大得多,我不喜欢必须为如此简单的任务运行它们。它们更适合于您想要维护tty的情况,通常是在远程机器上。
  2. 对于许多用户而言,可能希望查看您的外壳是否支持zsh之类的功能setopt nohup。可以用来指定SIGHUP退出外壳时不应将其发送到作业表中的作业。您可以在退出shell之前应用此选项,也可以将其添加到shell配置中,就像~/.zshrc您始终希望打开它一样。
  3. 找到一种编辑作业表的方法。我在tcsh或中找不到执行此操作的方法csh,这有点令人不安。
  4. 编写一个小的C程序来分叉和执行exec()。这是一个非常差的解决方案,但是源仅应包含几十行。然后,您可以将命令作为命令行参数传递给C程序,从而避免在Jobs表中输入特定于进程的信息。

29
  1. nohup $COMMAND &
  2. $COMMAND & disown
  3. setsid command

我使用2号已经很长时间了,但是3号也一样。另外,disown具有的nohup标志-h,可以使用放弃所有进程-a,并且可以使用放弃所有正在运行的进程-ar

静音是通过完成的$COMMAND &>/dev/null

希望这可以帮助!


简短而甜美;感谢您提供的非常有用的摘要!
谢尔约翰

我不敢相信我仍会收到此帖子的通知……
Minty Fresh先生

9

我认为屏幕可以解决您的问题


9

在tcsh(以及可能在其他shell中)中,可以使用括号将过程分离。

比较一下:

> jobs # shows nothing
> firefox &
> jobs
[1]  + Running                       firefox

对此:

> jobs # shows nothing
> (firefox &)
> jobs # still shows nothing
>

这将从作业列表中删除了Firefox,但仍与终端绑定。如果您通过“ ssh”登录到该节点,则尝试注销仍然会挂起ssh进程。



7

要解除tty shell的关联,请通过子shell运行命令,例如

(命令)&

退出时,使用的终端已关闭,但过程仍然有效。

检查-

(sleep 100) & exit

打开其他终端

ps aux | grep sleep

流程仍然存在。


这正是我所需要的。我试图添加一个用于Sublime Text的控制台快捷方式,它的工作原理非常好,这就是我最终得到的结果:(“ / opt / Sublime Text 2 / sublime_text” $ @)&
Ron E

5

为工作设置背景和前景可能是每个Unix系统管理员都应该了解的第一件事。

使用bash的方法如下:

./script.sh
# suspend process
{ctrl-Z}
# background process
bg
# list all backgrounded jobs
jobs
# bring it back to foreground
fg

4

您可以使用nohup命令运行命令,这将分离您的进程并将输出重定向到给定文件...但是我不确定这正是您所需要的..


我可以发誓,在使用exec之前我曾尝试过nohup-但显然不正确,因为它确实可以像这样工作:nohup gnome-terminal -e“ vim $ @”&> / dev / null&

2

尝试守护程序 -应该可以从友好的软件包管理器处获得,并全面照顾从终端解除关联的各种方法。


2

只需将其添加到您的bashrc / zshrc中:

detach() {
  "$@" 1>/dev/null 2>/dev/null &; disown
}

然后,您可以运行这样的无用命令:

detach gedit ~/.zshrc

1

在我的.bashrc中,我正是出于以下目的具有以下功能:

function run_disowned() {
    "$@" & disown
}

function dos() {
    # run_disowned and silenced

    run_disowned "$@" 1>/dev/null 2>/dev/null
}

在与dos终端分离的命令前面加上命令以运行它。

该函数被编写为与bash和一起使用zsh


1
我对此感到有些困惑,为什么这个答案只用一个函数包装到另一个函数中,当它足以将一个函数与这样的主体一起使用时: ( "$@" & disown) &> /dev/null。使用1>和也没有多大意义2>,因为您正在使用disown,这意味着您正在使用bash,并且在bash中,您可以轻松地&>进行重定向stdout和stderr的操作
Sergiy Kolodyazhnyy

我有两个功能,因为(1)我认为这样更容易阅读,并且(2)run_disowned我的dotfile文件中的其他位置都需要该功能。您&>当然是对的。
mic_e

0

我发现在Mac OS X上,我需要同时使用nohup和disown来确保子进程不会被终端拆除。


0

我使用以下脚本来执行此操作。nohup如果命令在中结束,它将停止到终端的打印过程,与之分离,并以返回状态退出TIMEOUT

#!/bin/bash

TIMEOUT=0.1

CMD=( "$@" )
#Could have some shortcuts here, e.g. replace "somefile.c" with "gedit somefile.c"

#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
#print the command for debugging and to see bash variable expansion
printf "%q " "${CMD[@]}"
echo
nohup "${CMD[@]}" >/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: $CMD"
#return the exit status of nohup, whatever it was
exit $NOHUP_STATUS

用法示例:

>>> run false
false
Error: false
>>> echo $?
1
>>> run true
true
>>> run sleep 10
sleep 10
>>>


-1

建议使用nohup回答许多问题。我宁愿建议使用pm2。在nohup上使用pm2具有许多优点,例如保持应用程序处于活动状态,维护应用程序的日志文件以及更多其他功能。有关更多详细信息,请查看

要安装pm2,您需要下载npm。对于基于Debian的系统

sudo apt-get install npm

对于Redhat

sudo yum install npm

或者您可以按照以下说明进行操作。安装npm后,使用它来安装pm2

npm install pm2@latest -g

完成后,您可以通过以下方式启动应用程序

$ pm2 start app.js              # Start, Daemonize and auto-restart application (Node)
$ pm2 start app.py              # Start, Daemonize and auto-restart application (Python)

对于过程监视,请使用以下命令:

$ pm2 list                      # List all processes started with PM2
$ pm2 monit                     # Display memory and cpu usage of each app
$ pm2 show [app-name]           # Show all informations about application

使用应用程序名称或进程ID管理进程,或一起管理所有进程:

$ pm2 stop     <app_name|id|'all'|json_conf>
$ pm2 restart  <app_name|id|'all'|json_conf>
$ pm2 delete   <app_name|id|'all'|json_conf>

日志文件位于

$HOME/.pm2/logs #contain all applications logs

1
使用NodeJS应用程序(而不是像nohup这样的小而强大的命令)来控制unix进程似乎……实在是太过分了,老实说,很奇怪。如果您需要重启功能,我将使用monit。
塞尔吉奥

@Sergio您可以选择使用专有应用程序。
鹰头18年

今年(一个4天前)已经发布了多个版本,所以我不知道您可能/为什么认为monit是已弃用的应用程序。@see mmonit.com/monit/changes
塞尔吉奥

我说的是nohup。
鹰头

1
nohup是普通的标准POSIX命令,所以同样的注释:绝不建议使用。@see unix.com/man-page/posix/1p/nohup
塞尔吉奥(Sergio)

-1

如果您的目标是仅启动命令行应用程序而不保留终端窗口,那么您可以在使用alt-F2启动终端后尝试运行该应用程序。

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.