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

How do I run a node.js app as a background service?

由于这篇文章在过去的几年里得到了广泛的关注,我已经在这篇文章的底部列出了每个平台的顶级解决方案。

原始职位:

我希望node.js服务器在后台运行,即:当我关闭终端时,我希望服务器继续运行。我在google上找到了这个教程,但是它并没有按预期工作。因此,我没有使用这个守护进程脚本,我认为我只是使用了输出重定向(2>&1 >> file部分),但这也不能退出-我的终端中有一个空行,就像它在等待输出/错误一样。

我也试着把这个过程放到后台,但是一旦我关闭终端,这个过程也会被终止。

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

顶级解决方案:

  • 系统(Linux)
  • Launchd(MAC)
  • 节点窗口(Windows)
  • PM2(节点JS)


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

2015年的答案:几乎每个Linux发行版都有SystemD,这意味着永久、monit等不再是必需的——您的操作系统已经处理了这些任务。

制作一个myapp.service文件(显然,用你的应用的名字替换"myapp"):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[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版)中获得的,该版本还包括生成用于构建Linux/节点服务器(包括.service文件)的AWS/DigitalOcean/Azure CloudConfig的命令。


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


更新-正如下面的一个答案中提到的,PM2有一些非常好的功能永远不会出现。考虑使用它。

原始答案

使用NOHUP:

1
nohup node server.js &

编辑我想补充的是,接受的答案是真正的出路。我永远都在使用那些需要保持警惕的实例。我喜欢做npm install -g forever,所以它在节点路径中,然后只做forever start server.js


这可能不是公认的方法,但我是用屏幕来做的,尤其是在开发过程中,因为我可以把它恢复过来,并在必要时用它来愚弄它。

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

屏幕将分离,并在您注销后存活下来。然后你可以把它放回去做屏幕-R。点击屏幕手册了解更多细节。你可以给屏幕命名,如果你喜欢什么也可以。


2016更新:节点windows/mac/linux系列在所有操作系统中都使用一个通用的API,因此它绝对是一个相关的解决方案。但是,node linux生成systemv init文件。随着SystemD的普及,它实际上是Linux上更好的选择。如果有人想向node linux添加systemd支持,欢迎使用pr:-)

原始线程:

现在这是一个非常古老的线程,但是节点窗口提供了在Windows上创建后台服务的另一种方法。它松散地基于在节点脚本周围使用exe包装器的nssm概念。但是,它使用winsw.exe代替,并提供了一个可配置的节点包装器,以便对进程在失败时如何启动/停止进行更精细的控制。这些流程与任何其他服务一样可用:

enter image description here

在某些事件日志记录中,模块也会烘焙:

enter image description here

脚本的后台监控是通过代码完成的。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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\
ode\\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!
Visit 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或节点Gyp Magic来安装此程序。此外,它还获得了麻省理工学院和BSD的许可。

完全公开,我是这个模块的作者。它的设计是为了减轻操作人员所经历的痛苦,但是通过与操作系统已经提供的功能的紧密集成。我希望未来有同样问题的观众会发现它是有用的。


更新:我更新了PM2的最新版本:

对于许多用例,使用SystemD服务是管理节点流程最简单和最合适的方法。对于那些在单个环境中运行多个节点进程或独立运行节点微服务的用户来说,PM2是一个功能更加完整的工具。

网址:https://github.com/unitech/pm2

HTTP//PM2.IO

  • 它有一个非常有用的监视功能—>漂亮的"gui",用于使用pm2 monit或使用pm2 list的进程列表对多个进程进行命令行监视。
  • 有组织的日志管理
  • 其他材料:
    • Behavior configuration
    • Source map support
    • PaaS Compatible
    • Watch & Reload
    • Module System
    • Max memory reload
    • Cluster Mode
    • Hot reload
    • Development workflow
    • Startup Scripts
    • Auto completion
    • Deployment workflow
    • Keymetrics monitoring
    • API

如果您运行的是OSX,那么产生真正系统进程的最简单方法就是使用launchd来启动它。

构建一个这样的plist,并将其放入名为top-level-domain.your-domain.application.plist的/library/launchdaemons中(放置时需要根目录):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?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>
   
        <string>/usr/local/bin/node</string>
        <string>your-script-file</string>
    </array>

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

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

</dict>
</plist>

完成后,发出(作为根目录):

1
2
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


如果您只想在脚本完成之前不间断地运行它,那么您可以使用nohop,如本文答案中所述。然而,没有一个答案提供完整的命令,也记录了stdinstdout

1
nohup node index.js >> app.log 2>&1 &
  • >>表示追加到app.log上。
  • 2>&1确保错误也发送到stdout并添加到app.log中。
  • 结束的&确保当前终端与命令断开连接,以便继续工作。

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


我只是使用守护进程NPM模块:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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:
', err);
    return process.exit(-1);
  }
  console.log('Daemonized successfully with pid: ' + pid);

  // Your Application Code goes here
});

最近,我还使用来自TJ Holowaychuk的mon(1)来启动和管理简单的节点应用程序。


我使用主管进行开发。它只是工作。当您对.js文件管理器进行更改时,会自动在加载这些更改的情况下重新启动应用程序。

这里有一个指向其Github页面的链接

安装:

sudo npm install supervisor -g

您可以很容易地让它用-e来监视其他扩展名。我经常使用的另一个命令是-i来忽略某些文件夹。

您可以使用nohup和supervisor使您的节点应用程序在后台运行,即使在您注销之后。

sudo nohup supervisor myapp.js &


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

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

您还可以永远使用来启动服务器

1
forever start -c"npm start" ./

PM2还支持npm start

1
pm2 start npm -- start


公认的答案可能是最佳的生产答案,但对于快速黑客进行开发工作,我发现:

nodejs scriptname.js &不起作用,因为nodejs似乎吞没了&;,所以事情并没有让我在没有scriptname.js死机的情况下继续使用终端。

但我把nodejs scriptname.js放在一个.sh文件中,并且nohup sh startscriptname.sh &工作。

当然不是生产问题,但它解决了"我需要继续使用我的终端,不想启动5个不同的终端"的问题。


node.js作为Windows XP中的后台服务

  • 有关安装node.js+npm for windows的教程,请访问hacksparrow:http://www.hacksparrow.com/install-node-js-and-npm-on-windows.html。
  • 对于nnsm.exe的实现,可以访问tatham oddie,网址为:http://blog.tatham.oddie.com.au/2011/03/16/node-js-on-windows/。

安装:

  • 通过安装程序可执行文件安装wget http://gnuwin32.sourceforge.net/packages/wget.htm
  • 通过安装程序可执行文件安装git http://code.google.com/p/msysgit/downloads/list
  • 安装nssm http://nssm.cc/download/?page=通过将nnsm.exe复制到%windir%/system32文件夹进行下载
  • 创建c:odehelloworld.js

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 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
    ");
    });
    server.listen(8000);
    console.log("Server running at http://127.0.0.1:8000/");
  • 打开命令控制台并键入以下内容(仅当安装了资源工具包时才输入setx)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    C:
    ode> set path=%PATH%;%CD%
    C:
    ode> setx path"%PATH%"
    C:
    ode> set NODE_PATH="C:\Program Files
    odejs
    ode_modules"
    C:
    ode> git config --system http.sslcainfo /bin/curl-ca-bundle.crt    
    C:
    ode> git clone --recursive git://github.com/isaacs/npm.git    
    C:
    ode> cd npm    
    C:
    ode
    pm> node cli.js install npm -gf  
    C:
    ode> cd ..    
    C:
    ode> nssm.exe install node-helloworld"C:\Program Files
    odejs
    ode.exe" c:
    ode\helloworld.js    
    C:
    ode> net start node-helloworld
  • 一个漂亮的批处理程序是创建c:odeservice.cmd

    1
    2
    3
    4
    5
    6
    @echo off
    nssm.exe install node-%~n1"C:\Program Files
    odejs
    ode.exe" %~s1
    net start node-%~n1
    pause
  • 服务管理:

    • 现在可以通过start->run->services.msc或通过start->run->msconfig->services(并选中"hide所有Microsoft服务)。
    • 脚本将为通过批处理脚本生成的每个节点添加前缀"节点-"。
    • 同样,它们也可以在注册表中找到:"hklmsystemcurrentcontrolsetservicesode xxxx"

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

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

    启动服务:sudo服务nodejs start

    停止服务:sudo服务nodejs停止

    服务脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    description"DManager node.js server - Last Update: 2012-08-06"
    author     "Pedro Muniz - [email protected]"

    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


    2017年6月更新:Linux解决方案:(Red Hat)。以前的评论对我不起作用。这对我在亚马逊网络服务上有效——RedHat7。希望这对外面的人有用。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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
    1
    2
    3
    4
    5
    6
    7
    8
    9
    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)
    1
    2
    3
    4
    5
    6
    7
    8
    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


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

    1
    2
    3
    4
    nssm install <service name> <node path>  

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

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


    为了完善各种建议的选项,这里还有一个:gnu/linux中的daemon命令,您可以在这里阅读:http://libslack.org/daemon/manpages/daemon.1.html。(如果上述评论中已经提到了这一点,则表示歉意)。


    对于使用更新版本的守护进程NPM模块的用户,您需要传递文件描述符而不是字符串:

    1
    2
    3
    4
    5
    6
    7
    var fs = require('fs');
    var stdoutFd = fs.openSync('output.log', 'a');
    var stderrFd = fs.openSync('errors.log', 'a');
    require('daemon')({
        stdout: stdoutFd,
        stderr: stderrFd
    });

    有没有人注意到"2>1"的位置有点小错误?

    1
    2>&1 >> file

    应该是

    1
    >> file 2>&1


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


    看看赋格!除了启动许多工人,您还可以将您的节点进程妖魔化!

    网址:http://github.com/pgte/fugue


    PM2是node.js应用程序的生产流程管理器,具有内置的负载均衡器。它允许您永远保持应用程序的活动状态,在不停机的情况下重新加载应用程序,并方便执行常见的系统管理任务。网址:https://github.com/unitech/pm2


    我很惊讶没有人提到古夫纳

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

    enter image description here

    编辑:但是,我不确定它是否适用于Windows。我只在Linux上使用过它。


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

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

    我还在末尾添加了>> logfile位,这样就可以轻松地保存节点console.log()语句。

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

    这样,我就可以创建一个命令行选项,既可以让服务器继续运行,也可以在进行更改时重新启动它,这对开发非常有帮助。