如何将node.js应用程序作为后台服务运行?


503

由于这些年来引起了很多关注,因此我在文章的底部列出了每个平台的最佳解决方案。


原始帖子

我希望我的node.js服务器在后台运行,即:当我关闭终端时,我希望服务器继续运行。我已经用谷歌搜索并提出了本教程,但是它不能按预期工作。因此,我认为我只是使用了输出重定向(该2>&1 >> file部分),而不是使用该守护程序脚本,但这也不会退出-我在终端中出现空白行,就像它在等待输出/错误一样。

我也尝试过将进程置于后台,但是一旦关闭终端,进程也会被终止。

那么,当我关闭本地计算机时如何使它运行?


最佳解决方案


3
我认为他打算关闭自己的本地系统
Kamal Reddy 2013年

46
他的意思是关闭ssh会话将终止任务
thedjaney

5
github.com/Unitech/pm2是一个高度维护且非常稳定的过程管理器,请尝试一下!
Unitech

1
您可以使用屏幕(aperiodic.net/screen/quick_reference
karantan

Answers:


433

如何将Node.js应用程序作为自己的进程运行来复制我自己的答案

2015年的答案:几乎每个Linux发行版都随附systemd,这意味着永久,monit,PM2等都不再需要-您的OS已经可以处理这些任务

制作一个myapp.service文件(用您的应用名称替换“ myapp”):

[Unit]
Description=My app

[Service]
ExecStart=/var/www/myapp/app.js
Restart=always
User=nobody
# Note Debian/Ubuntu uses 'nogroup', RHEL/Fedora uses 'nobody'
Group=nogroup
Environment=PATH=/usr/bin:/usr/local/bin
Environment=NODE_ENV=production
WorkingDirectory=/var/www/myapp

[Install]
WantedBy=multi-user.target

请注意,如果您不熟悉Unix,则 /var/www/myapp/app.js应该#!/usr/bin/env node在第一行。

将您的服务文件复制到中/etc/systemd/system

从开始systemctl start myapp

使它能够在启动时运行systemctl enable myapp

查看日志 journalctl -u myapp

这取自我们如何在Linux版2018年上部署节点应用程序,该版本还包括用于生成AWS / DigitalOcean / Azure CloudConfig来构建Linux /节点服务器(包括.service文件)的命令。


4
Upstart,如果有的话,也是一个很好的解决方案。无论哪种方式,您都不应依赖nodejs进程来保持nodejs守护程序运行。这仅是OS的一项任务。killall和的NodeJS永远消失了......
131

19
请注意,也可以以用户身份运行systemd服务。例如,参见本教程。您可以放入服务文件~/.config/systemd/user,以开头,通过systemctl --user start myapp启用systemctl --user enable myapp
cdauth

5
感谢您的回答。这就是我想要的纯净和清晰
bmavus

5
我接受了这个答案,而不是“永远”的答案,因为我也认为这是最好的方法。对于Mac和Windows,也有类似的答案,但我想大多数人都在寻找Linux解决方案。
Peter Kruithof

11
在EC2 AMI路径中/ etc / systemd / system不存在。您能否指出AWS EC2 Linux AMI中的正确路径是什么?
勒内·米歇尔

241

您可以使用Forever,这是一个简单的CLI工具,用于确保给定的节点脚本连续(即,永远)运行:https : //www.npmjs.org/package/forever


4
对于最新节点,我无法通过脚本名称(错误)来停止应用程序-而且-通常行为异常(在OS-X上)-都是从源代码构建的,这很奇怪。让事情陷入困境,并没有使我充满信心。
Michael Neale

4
尽管nohup可以解决问题,但永远持续下去是一种更好的解决方案,因为它可以守护进程。很棒的工具!
Peter Kruithof

5
顺便说一句,这里提供了一个更简单的教程:使用Forever保持node.js服务器的正常运行
kehers 2012年

2
我确实使用了Forever一段时间,一开始一切似乎都还不错,但随后发生了灾难。Forever再也无法管理流程,而让它们疯狂运行。仍在努力寻找更好的解决方案。我将尝试使用nohup
LN

5
Geoffrey-不,您需要forever start /path/to/yourApp.js在服务器启动脚本中执行此操作。
mikermcneil

215

更新 -正如以下答案之一所述,PM2永远都缺少一些非常好的功能。考虑使用它。

原始答案

使用nohup

nohup node server.js &

编辑我想补充一下,接受的答案确实是正确的方法。我在需要保持正常运行的实例上永远使用。我喜欢这样做npm install -g forever,它在节点路径中,然后执行forever start server.js


136
要知道的很酷的部分:nohup代表no hangup过去的那个地方,当您“挂断”调制解调器时,您希望在那里保持进程的活力。
jAndy

1
如今,它更是信号1的名称,进程收到该警告以警告用户关闭了外壳(或丢失了调制解调器连接,当然是:P)
lapo 2011年

7
这不是最佳解决方案,因为如果应用程序遇到未捕获的错误,则节点进程将退出并且不会重新启动。尽管如此,它仍然是开发的合理选择。
Andy E

1
我该如何添加环境变量?例如:PORT = 80 node server.js
Pardoner 2012年

1
看看从SO这个答案- stackoverflow.com/questions/8825460/...
NG。

67

这可能不是被接受的方法,但是我使用屏幕来实现,尤其是在开发过程中,因为我可以将其备份并在必要时对其进行愚弄。

screen
node myserver.js
>>CTRL-A then hit D

屏幕将脱离,并在您注销后仍然存在。然后,您可以通过屏幕-r将其取回。点击屏幕手册获取更多详细信息。您可以命名屏幕,也可以根据需要命名。


2
另外,tmux很好。像屏幕一样工作(默认是CTRL-B而不是CTRL-A,但是它是可配置的)。Tmux具有面板(分屏)。
snapfractalpop 2012年

1
屏幕上也有面板
Billy Moon

我从流星应用程序使用了两个星期以来就一直使用它。有时可能需要$ screen -dr来分离和重新连接。
Vinay Vemula 2015年

对我来说,完成工作的最简单方法。但是我同意,不是最好的解决方案
Pomme De Terre

重新启动系统后,此解决方案无法持久
wnasich

60

2016更新: node-windows / mac / linux系列在所有操作系统上使用通用的API,因此绝对是一个相关的解决方案。然而; node-linux生成systemv初始化文件。随着systemd的持续流行,实际上它是Linux上更好的选择。如果有人想向node-linux添加systemd支持,则PR表示欢迎:-)

原始线程:

现在这是一个相当老的线程,但是节点窗口提供了另一种在Windows上创建后台服务的方法。它大致基于在节点脚本周围nssm使用exe包装器的概念。然而; 它winsw.exe改为使用它,并提供可配置的节点包装,以更精细地控制流程在故障发生时如何启动/停止。这些过程与其他服务一样可用:

在此处输入图片说明

该模块还包含一些事件日志记录:

在此处输入图片说明

守护脚本是通过代码完成的。例如:

var Service = require('node-windows').Service;

// Create a new service object
var svc = new Service({
  name:'Hello World',
  description: 'The nodejs.org example web server.',
  script: 'C:\\path\\to\\my\\node\\script.js'
});

// Listen for the "install" event, which indicates the
// process is available as a service.
svc.on('install',function(){
  svc.start();
});

// Listen for the "start" event and let us know when the
// process has actually started working.
svc.on('start',function(){
  console.log(svc.name+' started!\nVisit http://127.0.0.1:3000 to see it in action.');
});

// Install the script as a service.
svc.install();

该模块支持诸如限制重新启动的上限(这样,错误的脚本不会使您的服务器瘫痪)以及重新启动之间的时间间隔越来越长。

由于节点Windows服务的运行方式与其他服务一样,因此可以使用您已经使用的任何软件来管理/监视该服务。

最后,没有make依赖关系。换句话说,简单npm install -g node-windows易用。您不需要安装Visual Studio,.NET或node-gyp魔术。此外,它还获得了MIT和BSD的许可。

我完全是本模块的作者。它旨在减轻OP所遭受的确切痛苦,但与操作系统已提供的功能之间的紧密集成。我希望将来有同样问题的观众也能从中受益。


8
我现在将其移植到node-mac,在OSX上提供相同的功能。
科里

1
我的意思是安排一些Node程序,然后再决定选择Node-windows,Forever还是Kue。我倾向于节点窗口,但想了解为什么当我要计划和监视许多节点程序时不使用Forever或Kue。一些永远运行。也需要监视。
克里斯蒂安·韦斯特贝克

5
节点窗口使用本机OS管理后台服务,并使用本机事件日志进行日志记录。Forever拥有自己的自定义监视和日志记录。我在medium.com/p/2a602ea657a2上对此发表了一篇文章。 听起来您需要安排脚本,而不是一直将它们作为后台服务运行。为此设计了诸如Kue和Agenda之类的项目。节点窗口和永远服务于另一个目的。
科里

1
@Corey,我如何从终端运行node-mac中包含的示例?,我尝试了node install.js,但它似乎没有启动helloworld.js
Edwin Ikechukwu Okonkwo

@Edwin-最好打开一个新问题,其中包含有关您所使用的代码的更多详细信息。
科里

28

更新:我已更新为包括pm2中的最新内容:

对于许多用例,使用systemd服务是管理节点进程的最简单,最合适的方法。对于在单个环境中运行大量节点进程或独立运行节点微服务的用户而言,pm2是功能更强大的工具。

https://github.com/unitech/pm2

http://pm2.io

  • 它具有一个非常有用的监视功能->漂亮的'gui',用于使用pm2 monit或列出的多个进程进行命令行监视pm2 list
  • 有组织的日志管理-> pm2 logs
  • 其他的东西:
    • 行为配置
    • 源地图支持
    • 兼容PaaS
    • 观看并重新加载
    • 模块系统
    • 最大内存重载
    • 集群模式
    • 热装
    • 开发流程
    • 启动脚本
    • 自动完成
    • 部署工作流程
    • 关键指标监控
    • API

19

如果您正在运行OSX,则生成真实系统进程的最简单方法是使用launchd它来启动它。

建立一个这样的plist,然后将其放入名称为/ Library / LaunchDaemons的文件中top-level-domain.your-domain.application.plist(放置时需要为root用户):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>Label</key>
    <string>top-level-domain.your-domain.application</string>

    <key>WorkingDirectory</key>
    <string>/your/preferred/workingdirectory</string>

    <key>ProgramArguments</key>
    <array>
        <string>/usr/local/bin/node</string>
        <string>your-script-file</string>
    </array>

    <key>RunAtLoad</key>
    <true/>

    <key>KeepAlive</key>
    <true/>

</dict>
</plist>

完成后,发出此命令(作为根用户):

launchctl load /Library/LaunchDaemons/top-level-domain.your-domain.application.plist
launchctl start top-level-domain.your-domain.application

而你正在跑步。

重新启动后,您仍然可以运行。

有关plist中的其他选项,请参见此处的手册页:https : //developer.apple.com/library/mac/documentation/Darwin/Reference/Manpages/man5/launchd.plist.5.html


这将以什么用户身份运行服务?有没有设置用户的方法?
rjmunro '16

19

如果您只想不间断地运行脚本直到完成,则可以nohup按照此处的答案中所述使用。但是,所有答案均未提供完整的命令,也记录了stdinstdout

nohup node index.js >> app.log 2>&1 &
  • >>方法附加到app.log
  • 2>&1确保错误也发送到stdout并添加到了app.log
  • 结尾&确保您当前的终端与命令断开连接,以便您可以继续工作。

如果要运行节点服务器(或在服务器重新启动时应启动的备份服务器),则应使用systemd / systemctl


1
最佳答案M8。
bholagabbar

1
很好的解释
Prakhar Prakash Bhardwaj

15

如果您使用的是nohup,请尝试运行此命令-

nohup npm start 2>/dev/null 1>/dev/null&

您也可以永久使用来启动服务器

forever start -c "npm start" ./ 

PM2还支持 npm start

pm2 start npm -- start

2
thnx,这很好用。 pm2 start npm -- start
yadavr

13

我只是在使用守护程序 npm模块:

var daemon = require('daemon');

daemon.daemonize({
    stdout: './log.log'
  , stderr: './log.error.log'
  }
, './node.pid'
, function (err, pid) {
  if (err) {
    console.log('Error starting daemon: \n', err);
    return process.exit(-1);
  }
  console.log('Daemonized successfully with pid: ' + pid);

  // Your Application Code goes here
});

最近我还使用星期一(1)TJ Holowaychuk启动和管理简单节点的应用程序。


12

我使用Supervisor进行开发。它只是工作。每当您对.js文件进行更改时,Supervisor都会在加载这些更改后自动重新启动您的应用程序。

这是其Github页面的链接

安装:

sudo npm安装主管-g

您可以使用-e轻松使其监视其他扩展。我经常使用的另一个命令是-i忽略某些文件夹。

您甚至可以在注销后使用nohup和超级用户使节点应用程序在后台运行。

sudo nohup主管myapp.js&


1
我认为在实践中,主管比大多数守护程序模块更好,特别是与Webhook结合使用以签出更新。
伊恩·柯林斯

我第二把这个。如果更改PHP文件,是否要重新启动Apache或Nginx服务器?当然不。那为什么还要重新启动整个Node.js服务器甚至只更改一行代码呢?尽管这可能不是最佳解决方案,但与Supervisor租用时,您无需担心重新启动过程(实际上重新启动仍然会发生)。
张巴兹

7

Node.js作为WINDOWS XP中的后台服务

安装:

  1. 通过安装程序可执行文件安装WGET http://gnuwin32.sourceforge.net/packages/wget.htm
  2. 通过安装程序可执行文件安装GIT http://code.google.com/p/msysgit/downloads/list
  3. 通过将nnsm.exe复制到%windir%/ system32文件夹来安装NSSM http://nssm.cc/download/?page=download
  4. 创建c:\ node \ helloworld.js

    // http://howtonode.org/hello-node
    var http = require('http');
    var server = http.createServer(function (request, response) {
        response.writeHead(200, {"Content-Type": "text/plain"});
        response.end("Hello World\n");
    });
    server.listen(8000);
    console.log("Server running at http://127.0.0.1:8000/");
  5. 打开命令控制台并键入以下内容(仅在安装了Resource Kit的情况下才为setx)

    C:\node> set path=%PATH%;%CD%
    C:\node> setx path "%PATH%"
    C:\node> set NODE_PATH="C:\Program Files\nodejs\node_modules"
    C:\node> git config --system http.sslcainfo /bin/curl-ca-bundle.crt    
    C:\node> git clone --recursive git://github.com/isaacs/npm.git    
    C:\node> cd npm    
    C:\node\npm> node cli.js install npm -gf   
    C:\node> cd ..    
    C:\node> nssm.exe install node-helloworld "C:\Program Files\nodejs\node.exe" c:\node\helloworld.js    
    C:\node> net start node-helloworld
  6. 一个不错的批处理好事是创建c:\ node \ ServiceMe.cmd

    @echo off
    nssm.exe install node-%~n1 "C:\Program Files\nodejs\node.exe" %~s1
    net start node-%~n1
    pause

服务管理:

  • 现在可以通过开始->运行-> services.msc或通过开始->运行-> MSCONFIG->服务(并选中“隐藏所有Microsoft服务”)来访问服务本身。
  • 该脚本会将通过批处理脚本创建的每个节点添加为“ node-”前缀。
  • 同样,可以在注册表中找到它们:“ HKLM \ SYSTEM \ CurrentControlSet \ Services \ node-xxxx

7

公认的答案可能是最佳的生产答案,但是对于从事开发工作的快速黑客来说,我发现了这一点:

nodejs scriptname.js & 没用,因为nodejs似乎吞噬了&,因此事情没让我继续使用终端而没有scriptname.js死去。

但是我放nodejs scriptname.js了一个.sh文件,然后 nohup sh startscriptname.sh &工作了。

绝对不是生产产品,但是它解决了“我需要继续使用我的终端并且不想启动5个不同的终端”的问题。


4

如果您在Linux服务器上运行nodejs,我认为这是最好的方法。

创建服务脚本并复制到/etc/init/nodejs.conf

启动服务:sudo服务nodejs启动

停止服务:sudo服务nodejs停止

服务脚本

description "DManager node.js server - Last Update: 2012-08-06"
author      "Pedro Muniz - pedro.muniz@geeklab.com.br"

env USER="nodejs" #you have to create this user 
env APPNAME="nodejs" #you can change the service name
env WORKDIR="/home/<project-home-dir>" #set your project home folder here
env COMMAND="/usr/bin/node <server name>" #app.js ?

# used to be: start on startup
# until we found some mounts weren't ready yet while booting:
start on started mountall
stop on shutdown

# Automatically Respawn:
respawn
respawn limit 99 5

pre-start script
    sudo -u $USER echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/$APPNAME.log
end script

script
    # Not sure why $HOME is needed, but we found that it is:
    export HOME="<project-home-dir>"  #set your project home folder here
    export NODE_PATH="<project node_path>"

    #log file, grant permission to nodejs user
    exec start-stop-daemon --start --make-pidfile --pidfile /var/run/$APPNAME.pid --chuid $USER --chdir $WORKDIR --exec $COMMAND >> /var/log/$APPNAME.log 2>&1
end script

post-start script
   # Optionally put a script here that will notifiy you node has (re)started
   # /root/bin/hoptoad.sh "node.js has started!"
end script

pre-stop script
    sudo -u $USER echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Stopping" >> /var/log/$APPNAME.log
end script

4

2017年6月更新:
Linux解决方案:(红色帽子)。以前的评论对我不起作用。这在Amazon Web Service-Red Hat 7上对我有用。希望对某些人有用。

A. Create the service file 
sudo vi /etc/systemd/system/myapp.service
[Unit]
Description=Your app
After=network.target

[Service]
ExecStart=/home/ec2-user/meantodos/start.sh
WorkingDirectory=/home/ec2-user/meantodos/

[Install]
WantedBy=multi-user.target

B. Create a shell file
/home/ec2-root/meantodos/start.sh
#!/bin/sh -
sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080
npm start

then:
chmod +rx /home/ec2-root/meantodos/start.sh
(to make this file executable)

C. Execute the Following

sudo systemctl daemon-reload
sudo systemctl start myapp
sudo systemctl status myapp

(If there are no errors, execute below.  Autorun after server restarted.)
chkconfig myapp -add

非常有趣,我只是iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to 8080对它的功能感到好奇。请给我更多细节。我不确定,但是我认为它会将流量重定向808080侦听哪个节点服务器,对吗?
Shakiba Moshiri

3

使用nssm作为Windows的最佳解决方案,只需下载nssm,将cmd打开到nssm目录并键入

nssm install <service name> <node path> <app.js path> 

eg: nssm install myservice "C:\Program Files\nodejs" "C:\myapp\app.js" 

这将安装一个新的Windows服务,该服务将在services.msc处列出,您可以从中启动或停止该服务,该服务将自动启动,并且可以配置为在失败时重新启动。




1

有没有人注意到“ 2>&1”位置的一个小错误?

2>&1 >> file

应该

>> file 2>&1

1

我将tmux用于远程主机上的多窗口/窗格开发环境。分离并保持进程在后台运行非常简单。看看tmux


1

对于使用较新版本的守护程序 npm模块的用户-您需要传递文件描述符而不是字符串:

var fs = require('fs');
var stdoutFd = fs.openSync('output.log', 'a');
var stderrFd = fs.openSync('errors.log', 'a');
require('daemon')({
    stdout: stdoutFd, 
    stderr: stderrFd
});


0

我很惊讶没有人提到古弗诺尔

我一直在尝试pm2等。但是,当涉及到可靠控制和基于Web的性能指标时,我发现Guvnor迄今为止是最好的。另外,它也是完全开源的。

在此处输入图片说明

编辑:但是,我不确定它是否可以在Windows上运行。我只在Linux上使用过它。


4
截至2017年似乎已过时。构建失败。去年没有代码推送。可疑的。
azatar

0

由于我在提供的答案列表中缺少此选项,因此我想在2020年之前添加一个合格的选项:docker或任何等效的 容器平台。除了确保您的应用程序在稳定的环境中运行之外,还具有其他安全优势以及改进的可移植性。

Docker支持Windows,macOS和大多数/主要的Linux发行版。在受支持的平台上安装docker非常简单明了,并且有据可查。设置Node.js应用程序非常简单,只需将其放入容器中并运行该容器,同时确保它在关闭后重新启动。

创建容器映像

假设您的应用程序在该服务器上的/ home / me / my-app中可用,在文件夹/ home / me / my-app中创建一个文本文件Dockerfile,其内容类似于以下内容:

FROM node:lts-alpine
COPY /my-app /app
CMD ["/app/server.js"]

使用以下命令创建图像:

docker build -t myapp-as-a-service /home/me

注意:最后一个参数是选择包含该Dockerfile的文件夹,而不是Dockerfile本身。您可以使用选项-f选择其他选项。

启动容器

使用以下命令启动容器:

docker run -d --restart always -p 80:3000 myapp-as-a-service

此命令假定您的应用程序正在侦听端口3000,并且您希望它在主机的端口80上公开。

当然,这是一个非常有限的示例,但这是一个很好的起点。


0

如果您使用的是pm2,则可以将其autorestart设置为false

$ pm2生态系统

这将生成一个示例ecosystem.config.js

module.exports = {
  apps: [
    {
      script: './scripts/companies.js',
      autorestart: false,
    },
    {
      script: './scripts/domains.js',
      autorestart: false,
    },
    {
      script: './scripts/technologies.js',
      autorestart: false,
    },
  ],
}

$ pm2启动ecosystem.config.js


-1

对于这个聚会来说,这个答案很晚了,但是我发现最好的解决方案是编写同时使用screen -dmSnohup命令的shell脚本。

screen -dmS newScreenName nohup node myserver.js >> logfile.log

我还在>> logfile末尾添加了一点,以便可以轻松保存node console.log()语句。

为什么要使用Shell脚本?好吧,我还添加了一个if语句,用于检查node myserver.js进程是否已在运行。

这样,我可以创建一个命令行选项,该选项既可以使服务器保持运行状态,也可以在进行更改后重新启动服务器,这对开发非常有帮助。


2
我遇到了这个问题,对Linux来说还很陌生。没有屏幕或nohup怎么办?
克雷格·诺顿
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.