如何将Node.js作为后台进程运行并且永不消亡?


480

我通过腻子SSH连接到linux服务器。我试图将其作为这样的后台进程运行:

$ node server.js &

但是,在2.5小时后,终端变为非活动状态,该过程终止。无论如何,即使在终端断开连接的情况下,我仍然可以保持该过程正常进行吗?


编辑1

实际上,我尝试过nohup,但是一旦关闭Putty SSH终端或拔出Internet插头,服务器进程就会立即停止。

在腻子里我有什么需要做的吗?


编辑2(2012年2月)

永远有一个node.js模块。它将作为守护程序服务运行node.js服务器。


7
就我而言,当我通过键入退出Terminal时,nohup起作用exit。当我只关闭腻子窗口时,它会失败。
Pawel Furmaniak

Answers:


513

简单的解决方案(如果您对返回该过程不感兴趣,只希望它继续运行):

nohup node server.js &

还有一个jobs命令可以查看这些后台进程的索引列表。您可以通过运行kill %1kill %2将数字作为该进程的索引来杀死后台进程。

强大的解决方案(如果它是交互式的,则允许您重新连接到该过程):

screen

然后,您可以通过按Ctrl + a + d进行分离,然后通过运行重新附加 screen -r

还可以考虑使用新的替代屏幕tmux。


1
因此,如果我运行“屏幕”,那么我将创建屏幕并在其中运行,对吗?
murvinlai 2011年

30
是的,然后可以通过按Ctrl + a,d进行分离,然后通过运行屏幕-r
MK

1
@murvinlai EC2是一个环境,与root特权无关。这可能与您的AMI有关。例如,使用Amazon AMI,您当然可以sudo bash
帅苑2013年

1
man bash:如果命令被控制操作符&终止,则shell在子shell的后台执行该命令。外壳不会等待COM的普通话到结束,返回状态是0
MK。

34
请阅读本文的任何人:在屏幕或tmux会话中运行node.js服务器是AMATEUR解决方案!除非进行快速测试,否则不要这样做。要保持进程运行,您需要守护它!为此使用适当的工具,例如foreverpm2或简单的旧init.d脚本
维克多·施罗德

1119

nohup node server.js > /dev/null 2>&1 &

  1. nohup表示:即使关闭了笔风也不要终止此过程。
  2. > /dev/null表示:stdout转到/ dev / null(这是一个不记录任何输出的虚拟设备)。
  3. 2>&1表示:stderr也转到stdout(已重定向到/dev/null)。您可以将&1替换为文件路径,以记录错误日志,例如:2>/tmp/myLog
  4. &最后的意思是:将此命令作为后台任务运行。

49
这应该是公认的答案,因为它的质量比当前公认的更高。
L0j1k 2014年

2
@ L0j1k值得商bat,OP已经显示出一定的理解水平,即接受的答案需要进一步的解释。
JFA 2014年

41
SO与OP无关,而是与OP的数千人寻求帮助有关。
L0j1k 2014年

3
是否需要重定向stdout和stderr?如果我根本不重定向它们,它也会一样好吗?还是如果我将它们重定向到文件?
肖恩2014年

10
发送stdout和stderr给/dev/null?很好的日志记录...尝试调试此消息的好运...
VictorSchröder'16

138

您确实应该尝试使用screen。这比仅仅做起来要复杂一些nohup long_running &,但是一旦您再也没有回来,便要了解屏幕。

首先开始您的屏幕会话:

user@host:~$ screen

运行任何您想要的:

wget http://mirror.yandex.ru/centos/4.6/isos/i386/CentOS-4.6-i386-binDVD.iso

按ctrl + A,然后按d。做完了 您的会话一直在后台进行。

您可以按列出所有会话screen -ls,并按screen -r 20673.pts-0.srv命令附加到某些会话,其中0673.pts-0.srv是条目列表。


125

这是一个老问题,但在Google上排名很高。我几乎不敢相信投票赞成率最高的答案,因为在屏幕会话内运行带有&甚至带有该nohup标志(全部)的node.js进程只是解决方法。

特别是屏幕/ tmux解决方案,应该真正将其视为业余解决方案。Screen和Tmux并不是要保持进程运行,而是用于多路复用终端会话。很好,当您在服务器上运行脚本并希望断开连接时。但是对于node.js服务器,您不希望将进程附加到终端会话。这太脆弱了。为了保持运行状态,您需要守护进程!

有很多好的工具可以做到这一点。

PM2http//pm2.keymetrics.io/

# basic usage
$ npm install pm2 -g
$ pm2 start server.js

# you can even define how many processes you want in cluster mode:
$ pm2 start server.js -i 4

# you can start various processes, with complex startup settings
# using an ecosystem.json file (with env variables, custom args, etc):
$ pm2 start ecosystem.json

我看到支持PM2的一大优势是,它可以生成系统启动脚本,以使进程在两次重启之间保持不变:

$ pm2 startup [platform]

哪里platform可以ubuntu|centos|redhat|gentoo|systemd|darwin|amazon

forever.jshttps//github.com/foreverjs/forever

# basic usage
$ npm install forever -g
$ forever start app.js

# you can run from a json configuration as well, for
# more complex environments or multi-apps
$ forever start development.json

初始化脚本

我不会详细介绍如何编写初始化脚本,因为我不是该主题的专家,并且对于这个答案来说太长了,但是基本上它们是由OS事件触发的简单shell脚本。您可以在此处了解更多信息

码头工人

只需在带有-d选项的Docker容器中运行服务器,,您就有了一个守护进程的node.js服务器!

这是一个示例Dockerfile(来自node.js 官方指南):

FROM node:argon

# Create app directory
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

# Install app dependencies
COPY package.json /usr/src/app/
RUN npm install

# Bundle app source
COPY . /usr/src/app

EXPOSE 8080
CMD [ "npm", "start" ]

然后构建图像并运行容器:

$ docker build -t <your username>/node-web-app .
$ docker run -p 49160:8080 -d <your username>/node-web-app

希望这有助于有人登陆此页面。始终使用正确的工具进行作业。它将为您省去很多头痛,甚至数小时!


2
这就是我想要的。使用pm2解决方案,以后是否可以将终端连接到终端?
量化

4
@量化,不。这是不可能的,因为该过程未在交互式会话中运行。但是,tail -f通过查看pm2生成的日志文件,您可以具有相同的“感觉” 。
维克多·施罗德

1
您指定screen许多人正在寻找的解决方案来解决此问题。有许多方法可以完成特定任务。我认为碰巧(考虑到具体问题)恰好实现了run as background and never die许多人出色的具体任务。它还具有额外的好处,即允许用户返回到其中进行重新交互并根据需要进行更改。关键是组件是backgroundnever die。所有解决方案都有一定的好处。
LD詹姆斯

@Rakshith Ravi-我不同意。这些都需要额外的下载/软件/工具(init解决方案除外,该解决方案未提供解决方案)。的nohup 解决方案。它已经被移植到Linux中,并且正是它的目的所在。这是一条线,很干净,每次都可以按预期工作,无论更新如何。人们应该真正避免在诸如此类的基本用例中使用第三方工具。例如,与上面投票最多的答案中的一个简单命令相比,docker示例更加冗长且占用大量资源。喜欢Docker,但不要这样做。
Jack_Hu

1
@Jack_Hu,我对开销没有疑问,但是nohup解决方案不能满足“永不死”的要求。除非您编写了一个非常棘手trap或棘手的无限循环,否则我不明白如何在不使用专门为此目的编写的工具(或者当然是您自己编写的初始化脚本)的情况下守护进程。
维克多·施罗德

24

另一个解决方案取消了工作

$ nohup node server.js &
[1] 1711
$ disown -h %1

disown正是我想要的,但是-h标志有什么作用?我在手册中找不到它
Rimantas Jacikevicius

from手册页:如果指定了-h选项,则不会从表中删除每个jobspec,但会对其进行标记,以便如果shell收到SIGHUP,则不会将SIGHUP发送到该作业。如果未提供jobspec,则-a选项表示删除或标记所有作业;
myururdurmaz '16

14

nohup即使终端死机也将允许程序继续。实际上,我遇到了nohup阻止SSH会话正确终止的情况,因此您也应该重定向输入:

$ nohup node server.js </dev/null &

根据nohup配置方式,您可能还需要将标准输出和标准错误重定向到文件。


7

根据@Yoichi的回答,我的shell rc文件中具有此功能:

nohup-template () {
    [[ "$1" = "" ]] && echo "Example usage:\nnohup-template urxvtd" && return 0
    nohup "$1" > /dev/null 2>&1 &
}

您可以通过以下方式使用它:

nohup-template "command you would execute here"

7

Nohup和screen为在后台运行Node.js提供了很好的轻巧解决方案。Node.js流程管理器(PM2)是用于部署的便捷工具。使用npm在系统上全局安装它:

npm install pm2 -g

将Node.js应用程序作为守护程序运行:

pm2 start app.js

您可以选择将其链接到Unitech 生产的监控SAAS Keymetrics.io


6
$ disown node server.js &

它将从活动任务列表中删除命令,并将命令发送到后台



3

要使用sysv init在debian上将命令作为系统服务运行:

复制框架脚本并使其适应您的需要,可能您要做的就是设置一些变量。/lib/init/init-d-script如果某些脚本不符合您的需求,您的脚本将继承的默认值-在脚本中覆盖它。如果出现问题,您可以在source中查看详细信息/lib/init/init-d-script。强制变量为DAEMONNAME。脚本将用于start-stop-daemon运行您的命令,START_ARGS您可以在其中定义start-stop-daemon要使用的其他参数。

cp /etc/init.d/skeleton /etc/init.d/myservice
chmod +x /etc/init.d/myservice
nano /etc/init.d/myservice

/etc/init.d/myservice start
/etc/init.d/myservice stop

这就是我为Wikimedia Wiki运行一些python东西的方式:

...
DESC="mediawiki articles converter"
DAEMON='/home/mss/pp/bin/nslave'
DAEMON_ARGS='--cachedir /home/mss/cache/'
NAME='nslave'
PIDFILE='/var/run/nslave.pid'
START_ARGS='--background --make-pidfile --remove-pidfile --chuid mss --chdir /home/mss/pp/bin'

export PATH="/home/mss/pp/bin:$PATH"

do_stop_cmd() {
    start-stop-daemon --stop --quiet --retry=TERM/30/KILL/5 \
        $STOP_ARGS \
        ${PIDFILE:+--pidfile ${PIDFILE}} --name $NAME
    RETVAL="$?"
    [ "$RETVAL" = 2 ] && return 2
    rm -f $PIDFILE
    return $RETVAL
}

除了设置vars外,do_stop_cmd由于python替代了可执行文件,我还不得不重写它,因此服务无法正常停止。


3

除了上述出色的解决方案之外,我还提到了监督和监视工具,这些工具可用于启动过程,监视其存在并在其死后启动它。使用“ monit”,您还可以运行一些活动检查,例如检查进程是否响应http请求


3

对于Ubuntu,我使用以下命令:

(执行PROG_SH&> / dev / null&)

问候


次要点:如果PROG_SH是可执行文件,则不需要'exec'。David提出的解决方案的重点是使孩子脱离当前正在运行的外壳。孩子的父母成为“ pid 1”,并且在外壳终止时不会受到影响。
SoloPilot

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.