如何将一个进程完全从终端中分离出来?
我在Ubuntu上使用Tilda(下拉式终端)作为我的 “命令中心”–就像其他人使用GNOME Do、Quicksilver或Launchy一样。防止这样一个(非)子进程
- 在关闭源终端时被终止
- 通过 STDOUT/STDERR “污染 "源终端。
首先;一旦你启动了一个进程,你可以通过先停止它(按Ctrl-Z键),然后键入bg
让它在后台恢复。这时它就成了 “工作",它的stdout
/stderr
/stdin
仍然与你的终端连接。
你可以通过在它的结尾加上”&“来立即启动一个进程作为后台运行:
firefox &
要在后台静音运行,用这个方法:
firefox </dev/null &>/dev/null &
一些附加信息。
nohup
是一个程序,你可以用**来运行你的程序,这样它的stdout/stderr可以被发送到一个文件中,这样关闭父脚本就不会对子脚本进行SIGHUP。但是,你需要在启动程序之前就有先见之明的意识来使用它。由于nohup
的工作方式,你不能直接将它_应用到一个正在运行的进程中去。这基本上意味着你不能再使用disown
、fg
了,更重要的是,当你关闭shell的时候,它不会再挂起或发送一个bg
给那个子进程了。与SIGHUP
不同的是,nohup
是在进程被启动和背景化后使用的。
你不能做的是,在启动进程后改变它的stdout/stderr/stdin。至少不能从shell中改变进程的tdout/stderr/stdin。如果你启动了进程,并告诉它它的stdout是你的终端(默认情况下是这样做的),那么这个进程就会被配置成输出到你的终端。你的 shell 与进程的 FD 设置无关,那纯粹是进程本身管理的事情。进程本身可以决定是否关闭它的stdout/stderr/stdin,但你不能用shell来强迫它这样做。但对于那些你启动了但忘了静音的交互式进程(disown
),你就没办法了。有了screen,你可以在进程的输出变得麻烦的时候关闭正在运行的shell,然后打开一个新的shell(firefox < /dev/null &>/dev/null &
)。
哦,对了,不要在使用”screen
“的地方使用它。
^Ac
的意思是,$@
, $@
, $1
, $2
………..,这样你的命令就会变成:
gnome-terminal -e "vim $1" "$2" "$3" ...
这可能不是你想要的,因为-e只需要一个参数。用$3
来表示你的脚本只能处理一个参数。
在你给出的场景中,要让多个参数正常工作是非常困难的(用$1
),因为gnome-terminal -e
只需要一个参数,也就是一个shell命令字符串。你必须把你的参数编码成一个。最好的、最稳健的方法是这样的:
gnome-terminal -e "vim $(printf "%q " "$@")"
```。
如果你正在使用bash
,请尝试使用disown [jobspec]
;参见bash(1).
另一个可以尝试的方法是at now
。如果你不是超级用户,你使用at
的权限可能会受到限制。
读了这些答案,我最初的印象是发出nohup <command> &
就够了。在gnome-terminal中运行zsh,我发现nohup <command> &
并没有阻止我的shell在退出时杀死子进程。虽然nohup
很有用,特别是在非交互式shell中,但只有在子进程没有重置SIGHUP
信号的处理程序的情况下,它才会保证这种行为。因此,当终端模拟器退出时,它仍然可以杀死你的子进程。据我所知,这只能通过确保将进程从shell的作业表中删除来解决。如果nohup
是用shell内建的进程重写,就像有时的情况一样,这可能就足够了,然而,如果不是这样的话…..
SIGHUP
是shell内建的进程,nohup
,disown
,
<command> &
disown
,如果你喜欢单行本的话,
<command> &; disown
。这样做的效果一般是将子进程从作业表中删除。这样可以让你退出终端仿真器,而不会不小心给子进程发出信号。不管bash
处理程序是什么样子的,这应该不会杀死你的子进程。
disown之后,这个进程仍然是你的终端仿真器的子进程(如果你想看这个动作的话,可以玩玩zsh
),但是在终端仿真器退出之后,你应该看到它连接到init进程上。换句话说,一切都像你所希望的那样,也是你所希望的那样。
如果你的shell不支持ksh93
,该怎么办?我强烈建议换一个支持的,但是在没有这个选项的情况下,你有几个选择。
1.SIGHUP
和pstree
可以解决这个问题,但是它们的重量要重得多,我不喜欢为了这么简单的任务而运行它们。它们更适合于你想维护一个tty的情况,通常是在远程机器上。
2. 对于很多用户来说,看一下你的shell是否支持像zsh的disown
这样的能力,可能是比较可取的。这可以用来指定当shell退出时,screen
不应该被发送到jobs表中的jobs表中。你可以在退出shell之前就应用这个功能,或者在shell配置中添加这个功能,比如tmux
,如果你想让它一直开启的话。找到一个编辑作业表的方法。我在setopt nohup
或SIGHUP
中找不到方法,这有点困扰。
4. 写一个小的C程序来分叉和~/.zshrc
。这个方案很差,但是源码应该只有几十行,就可以了。这样就可以把命令作为命令行参数传递给C程序,这样就可以避免在作业表中出现进程特定的条目。
1.nohup $COMMAND &
2.$COMMAND & disown
3.setsid command
我用了很长时间的2号,但3号的效果一样好。另外,disown
有一个nohup
的标志,可以用-h
废止所有进程,可以用-a
废止所有运行中的进程,
静音是由-ar
来完成的,希望对你有帮助!
最简单也是唯一的正确答案:
command & disown
&001
你不需要将进程从终端中分离出来,而是从shell中分离出来。
在 tcsh 中(也许在其他 shell 中也是如此),你可以使用括号来分离进程。
只要在你的 bashrc/zshrc 中添加这样的命令:
detach() {
"$@" 1>/dev/null 2>/dev/null &; disown
}
然后你就可以像这样运行禁用命令:
detach gedit ~/.zshrc
很多答案都建议用nohup。我建议使用pm2。使用pm2比起nohup有很多优点,比如保持应用程序的活力,维护应用程序的日志文件,以及更多其他的功能。更多详情,请看这里 ](http://pm2.keymetrics.io/docs/usage/quick-start/). 要安装pm2,你需要下载npm。对于基于Debian的系统
sudo apt-get install npm
sudo yum install npm
,对于Redhat的系统
npm install pm2@latest -g
,或者你可以按照这些说明。在安装了npm后,使用它来安装pm2
$ 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
启动你的应用程序。