如何将Node.js作为后台进程运行并保持不间断?

503

我通过 Putty SSH 连接到 Linux 服务器,尝试以后台进程运行:

$ node server.js &

然而,2.5小时后终端变得不活跃,进程就会死亡。有没有办法让进程保持运行状态,即使终端断开连接?


编辑1

实际上,我尝试过nohup,但是一旦我关闭Putty SSH终端或拔掉网络,服务器进程就立即停止了。

我需要在Putty中做些什么吗?


编辑2(2012年2月)

有一个node.js模块,叫做forever。它可以将node.js服务器作为守护进程运行。


8
在我的情况下,当我通过输入“exit”退出终端时,nohup 起作用。但当我只是关闭 Putty 窗口时,它会失败。 - Pawel Furmaniak
14个回答

1160

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

  1. nohup的意思是:即使 stty 被切断,也不要终止此进程。
  2. > /dev/null的意思是:将标准输出重定向到 /dev/null(这是一个虚拟设备,不记录任何输出)。
  3. 2>&1 的意思是:将标准错误输出也重定向到已经重定向到 /dev/null 的标准输出。你可以用文件路径代替 &1 来记录错误日志,例如:2>/tmp/myLog
  4. 末尾的 & 的意思是:将此命令作为后台任务运行。

52
这应该成为被采纳的答案,因为它比目前被采纳的答案质量要高得多。 - L0j1k
2
@L0j1k 有争议,但 OP 已经表现出了足够的理解水平,因此对于被接受的答案来说不需要更多的解释。 - Jacqlyn
43
SO并不只是关于发帖者本身,它更多地关乎成千上万前来寻求帮助的人们。 - L0j1k
3
需要重定向标准输出和标准错误流吗?如果我不进行重定向,是否也能正常工作?或者将它们重定向到文件中会有影响吗? - Shawn
11
把标准输出和标准错误都重定向到 /dev/null?这样记录日志可真够玩儿的了,如果要调试就祝你好运吧... - Victor Schröder
显示剩余6条评论

532

简单的解决方案(如果您不想回到进程并且只想让它继续运行):

nohup node server.js &

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

强大的解决方案(允许您重新连接到交互式进程):

screen

你可以通过按下Ctrl+a+d来分离,然后通过运行screen -r重新附加回来。

另外,请考虑替代screen的更新工具tmux。


1
那么,如果我运行“screen”,我创建了屏幕并在其中运行,对吗? - murvinlai
30
是的,然后您可以通过按Ctrl+a、d来分离,然后通过运行screen -r重新连接。 - MK.
1
@murvinlai EC2是一个环境,与root权限无关。这可能与您的AMI有关。例如,使用Amazon AMI,您肯定可以执行sudo bash - shuaiyuancn
1
那么显而易见的后续问题是,如何在系统首次启动时自动运行它? - jjxtra
40
请注意:对于任何阅读此内容的人,请不要使用在screen或tmux会话中运行node.js服务器这种业余解决方案,除非只是进行快速测试。如果要使进程持续运行,需要将其daemonize!使用适当的工具,如foreverpm2或旧式的init.d脚本 - Victor Schröder
显示剩余12条评论

142
这是一个老问题,但在Google上排名很高。我几乎不敢相信得到最多赞的答案,因为在screen会话中运行node.js进程,使用&甚至使用nohup标志 -- 它们都只是解决方法。
特别是screen / tmux解决方案,应该真正被认为是业余解决方案。Screen和Tmux不适用于保持进程运行,而是用于复用终端会话。当您在服务器上运行脚本并希望断开连接时,这很好。但对于node.js服务器,您不希望将进程附加到终端会话。这太脆弱了。为了使事情持续运行,您需要将进程做成守护程序!
有许多很好的工具可以执行此操作。
PM2:http://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.js: https://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

初始化脚本:

我不会详细介绍如何编写初始化脚本,因为我不是这个领域的专家,而且这对于本回答来说太长了,但基本上它们是由操作系统事件触发的简单shell脚本。你可以在这里阅读更多信息。

Docker:

只需使用-d选项在Docker容器中运行您的服务器,voilá,您就有了一个守护进程的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解决方案,是否有办法稍后附加终端? - Quantumplation
4
@Quantumplation,不行,因为该进程并未在交互式会话中运行。但是您可以通过tail -f命令跟踪pm2生成的日志文件来获得相同的“感觉”。 - Victor Schröder
1
您指定的“screen”解决方案是许多人发现可以胜任工作的一种变通方法。有很多实现特定任务的方法。我相信(考虑具体问题)它恰好实现了“作为后台运行且永不死亡”的特定任务,这对许多人来说非常出色。它还有一个额外的好处,即允许用户重新进入并进行更改。关键组件是“后台”和“永不死亡”。所有解决方案都有一定的优点。 - L. D. James
1
@Rakshith Ravi - 我不同意。这些都需要额外的下载/软件/工具(除了init解决方案,没有给出解决方案)。nohup 就是解决方案。它已经内置在Linux中,并且它存在的目的就是为此服务。它只有一行,干净简洁,每次都能按预期工作,无论更新如何。人们应该尽量避免使用第三方工具来处理基本用例。例如Docker示例比最高投票答案中的一个简单命令更冗长和资源密集。我喜欢Docker,但不适用于此。 - Jack_Hu
1
@Jack_Hu,我对开销没有疑问,但“nohup”解决方案无法满足“永不死亡”的要求。除非你编写一个非常巧妙的“trap”或者一个hacky无限循环,否则我不知道如何在不使用专门为此目的编写的工具(或者自己编写的init脚本)的情况下将进程守护化。 - Victor Schröder
显示剩余2条评论

140

你真的应该尝试使用 screen。它比仅仅执行 nohup long_running & 更复杂,但一旦理解了 screen,您将再也不会回头。

首先启动您的 screen 会话:

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命令附加到其中某些会话中,其中20673.pts-0.srv是一个条目列表。


“screen”旨在用于交互性操作;对于非交互式脚本,许多人认为“nohup”是最佳解决方案。 - rinogo

27

另一个解决方案是放弃这份工作

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

1
disown正是我正在寻找的,但-h标志是什么意思?我在手册中找不到它。 - Rimantas Jacikevicius
如果给出了-h选项,则不会从表中删除每个作业规范,而是标记该作业规范,以便在shell接收到SIGHUP时不向作业发送SIGHUP。如果未提供作业规范,则-a选项表示删除或标记所有作业; - myururdurmaz

16

nohup命令可以让程序在终端关闭后继续运行。我曾经遇到过nohup阻止SSH会话正确终止的情况,因此您应该同时重定向输入:

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

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


9

Nohup和screen提供了在后台运行Node.js的好方法。Node.js进程管理器(PM2)是一个非常方便的部署工具。使用npm在系统上全局安装它:

npm install pm2 -g

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

pm2 start app.js

你还可以选择将它与Keymetrics.io链接,这是由Unitech制作的监控SAAS。


7
$ disown node server.js &

它将从活动任务列表中移除命令并将其发送到后台。

7

我在我的shell rc文件中有这个函数,它基于@Yoichi的答案:

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

您可以这样使用它:
nohup-template "command you would execute here"

6

你读过关于nohup命令的介绍吗?


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接