我在Ubuntu上使用Tilda(下拉终端)作为“命令中心”,这几乎是其他人可能使用GNOME Do,Quicksilver或Launchy的方式。将进程(例如Firefox)从启动它的终端中分离出来-即,防止这样的(非)子进程


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

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


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

评论

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

这是这个问题的重复stackoverflow.com/questions/285015/…

Dup of:superuser.com/questions/177218/…

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

#1 楼

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

您可以通过在其末尾附加一个“&”来立即启动一个后台进程。 br />
firefox &


要在无声的背景下运行,请使用以下命令: info:

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

disown是内置的bash,可从shell的作业列表中删除shell作业。这基本上意味着您不能再在其上使用fgbg,但是更重要的是,当您关闭外壳时,它将不再挂起或将SIGHUP发送给该孩子。与nohup不同,disown在启动进程并使其后台运行后使用。

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

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

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


哦,顺便说一句,不要使用“ $@“在您使用它的地方。 br />那可能不是您想要的,因为-e只接受一个参数。使用$@来显示您的脚本只能处理一个参数。

在给定的情况下(使用),很难使多个参数正常工作,因为仅接受一个参数,即一个shell命令字符串。您必须将参数编码为一个。最好,最可靠但很笨拙的方式是这样的:

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


评论


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

– AnC
09年3月23日在21:33

真是一个奇妙而详尽的答案。 +1

– Teekin
11-10-19在16:06



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

– lhunath
2014年10月8日,12:47

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

– sjas
15年1月28日在19:15

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

– Stefan Seidel
16-09-23在19:08

#2 楼

nohup cmd &


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

评论


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

–lmat-恢复莫妮卡
2013年6月6日14:48

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

–nemo
15年3月4日在16:29

@nemo这意味着该进程没有被分离,但是如果shell退出,该过程将被分离(和init的孩子)。

–诺多林
16年4月8日在0:35

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

–nemo
16年4月8日,0:58

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

– Jiggunjer
16年8月25日在17:22

#3 楼

如果使用的是bash,请尝试disown [jobspec];
请参见bash(1)。

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

评论


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

–艾吉尔
09年3月23日在12:08

从来没有想过使用“ at”,谢谢你的想法!

– cadrian
2012年10月10日15:01

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

– Ninsuo
2013年4月12日19:23在

作为参考,这在zsh中也适用。

–编码器
2014年5月28日上午11:10

而且,disown似乎对gnome-terminal并没有达到预期的效果-终端退出时,被杀死的进程仍会被杀死。我想知道为什么/如何。

–凯尔·斯特兰德(Kyle Strand)
16-09-13在23:00

#4 楼

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

对于我来说,nohup应该可以防止挂断信号来自到达应用程序,但子应用程序(在本例中为VMWare Player)正在重置其SIGHUP处理程序。结果,当终端仿真器退出时,它仍然可能杀死您的子进程。据我所知,这只能通过确保从外壳的作业表中删除该过程来解决。如果nohup被内置的Shell覆盖(有时是这种情况),这可能就足够了,但是,如果disown不是内置的Shell,则足够了。


bashzshksh93,如果您更喜欢单线,请
<command> &
disown




<command> &; disown


。从作业表中删除子流程通常具有理想的效果。这样,您就可以退出终端仿真器,而根本不会意外发出子进程的信号。不管SIGHUP处理程序是什么样子,都不应杀死您的子进程。

取消后,该进程仍然是终端仿真器的子进程(如果要观看此过程,请与pstree一起播放)操作),但是在终端仿真器退出后,您应该看到它已附加到init进程中。换句话说,一切都是应有的状态,并且可能是您想要的。

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



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


#5 楼


nohup $COMMAND &
$COMMAND & disown
setsid command

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

通过$COMMAND &>/dev/null完成消音。

希望有帮助!

评论


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

–乔纳森·H
19年1月10日在10:20

我简直不敢相信我还会收到此帖子的通知...

– Minty Fresh先生
19 Mar 21 '19 at 0:41

#6 楼

对于bash而言,最简单,唯一正确的答案是:

command & disown


您不必将过程与终端分离,而与外壳分离。

#7 楼

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

#8 楼

在tcsh中(可能在其他shell中也是如此),可以使用括号将进程分离。

比较:从职位列表中找到的Firefox,但仍与终端绑定;如果您通过“ ssh”登录到该节点,尝试注销仍然会挂起ssh进程。

#9 楼

要取消tty shell的关联,请通过子Shell运行命令,例如

(命令)&

当退出使用终端关闭时,进程仍然存在。

检查-

(sleep 100) & exit


打开其他终端

ps aux | grep sleep


过程仍然存在。

评论


这正是我所需要的。我正在尝试为sublime文本添加控制台快捷方式,并且它可以完美运行,这就是我最终得到的结果:(“ / opt / Sublime Text 2 / sublime_text” $ @)&

–罗恩E
13年12月3日,21:10

#10 楼

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

这是使用bash的方法:

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


#11 楼

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

评论


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

– AnC
09年3月23日在12:30

#12 楼

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

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


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

#13 楼

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

#14 楼

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

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

function dos() {
    # run_disowned and silenced

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


dos前面加上命令以从终端分离地运行它。

该函数被编写为与bashzsh一起使用。

评论


当这个答案足以将一个函数与这样的主体一起使用时,我对此感到有些困惑:为什么这个答案只用一个函数包装到另一个函数中:使用1>和2>也没有多大意义,因为您使用的是disown,这意味着您使用的是bash,在bash中,您可以轻松地&&重定向stdout和stderr

– Sergiy Kolodyazhnyy
16年8月7日在18:53

我将其作为两个函数使用,是因为(1)我认为这样更容易阅读,以及(2)我的dotfile文件中的其他位置都需要run_disowned功能。当然,您对&>事情是正确的。

–mic_e
16年8月8日在7:17

#15 楼

来自KDE的kstart5(可通过kde-cli-tools软件包获得)
kstart5 my-command &

如果运行gui,我们同样可以管理x窗口的多个方面

源:Linuxhacks.org
披露:我是Linuxhacks.org的所有者。

#16 楼

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

#17 楼

我使用以下脚本来执行此操作。如果命令在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


#18 楼

sudo apt install ucommon-utils

pdetach command

你去了:)

#19 楼

要从当前的SSH会话中完全分离程序,请运行:
setsid nohup script.sh &

..并重定向所有日志(stderr和stdout),可以运行:
setsid nohup script.sh &>/tmp/script.log &


要再次检查您的进程是否分离,请运行:
ps -efj --forest

并查看分层进程树。

评论


看到您将setsid和nohup放在一起时,我非常困惑。我们可以使用-f选项运行setsid,因此它将始终在新进程中运行。如果您不希望nohup仍然打印到终端,请使用第二种方法(也可以删除部件setid)。有什么我不知道的吗?

– Tuananhcwrs
10月24日17:08



#20 楼

建议使用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


评论


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

–塞尔吉奥
17年5月28日在21:56



@Sergio是使用不赞成使用的应用程序的选择。

–骇客
17年5月28日在22:13

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

–塞尔吉奥
17年6月11日在17:31

我说的是nohup。

–架子
17年6月11日在17:39

nohup是一个普通的标准POSIX命令,所以同样的注释:绝不建议使用。 @请参阅unix.com/man-page/posix/1p/nohup

–塞尔吉奥
17年6月11日在17:49

#21 楼

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