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

Posted

技术标签:

【中文标题】如何将 Node.js 作为后台进程运行并且永不死亡?【英文标题】:How to run Node.js as a background process and never die? 【发布时间】:2011-06-15 09:16:03 【问题描述】:

我通过 putty SSH 连接到 linux 服务器。我尝试将它作为这样的后台进程运行:

$ node server.js &

但是,在 2.5 小时后,终端变为非活动状态并且进程终止。无论如何,即使终端断开,我也可以保持进程活跃?


编辑 1

其实我试过nohup,但是只要我关闭Putty SSH终端或拔掉我的互联网,服务器进程就会立即停止。

在 Putty 中我有什么需要做的吗?


编辑 2(2012 年 2 月)

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

【问题讨论】:

在我的情况下,当我通过输入exit 退出终端时,nohup 工作。当我关闭 Putty 窗口时,它失败了。 【参考方案1】:

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

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

【讨论】:

这应该是公认的答案,因为它的质量比目前公认的要高得多。 @L0j1k 值得商榷,OP 已经表现出一定程度的理解,接受的答案需要进一步解释。 SO 与 OP 无关,而是与成千上万的人来 OP 的问题寻求帮助有关。 是否需要重定向stdout和stderr?如果我根本不重定向它们,它是否也能正常工作?或者如果我将它们重定向到文件? 将标准输出和标准错误发送到/dev/null?不错的日志记录...祝您调试成功...【参考方案2】:

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

nohup node server.js &

还有jobs 命令可以查看这些后台进程的索引列表。您可以通过运行kill %1kill %2 来终止后台进程,编号是进程的索引。

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

screen

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

还要考虑屏幕的更新替代品 tmux。

【讨论】:

所以,如果我运行“屏幕”,我会创建屏幕并在其中运行,对吧? 是的,然后你可以通过按 Ctrl+a, d 分离,然后通过运行 screen -r 附加回来 @murvinlai EC2 是一个环境,与 root 权限无关。这可能与您的 AMI 有关。例如,使用 Amazon AMI,您当然可以sudo bash man bash:如果一个命令被控制操作符 & 终止,shell 会在一个子shell 中在后台执行该命令。 shell 不等待命令完成,返回状态为 0。 请阅读本文的任何人:在屏幕或 tmux 会话中运行 node.js 服务器是一种业余解决方案!不要那样做,除非是为了快速测试。要保持进程运行,您需要对其进行daemonize!为此使用适当的工具,例如forever、pm2 或普通的旧init.d scripts。【参考方案3】:

你真的应该尝试使用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 是一个条目列表。

【讨论】:

screen 旨在用于交互性;对于非交互式脚本,许多人会认为nohup 是规范的解决方案。【参考方案4】:

这是一个老问题,但在 Google 上排名很高。我几乎不敢相信投票最高的答案,因为在屏幕会话中运行 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 脚本,由操作系统触发事件。你可以阅读更多关于这个here

Docker

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

这是一个示例 Dockerfile(来自 node.js official guide):

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

希望这有助于有人登陆此页面。始终使用合适的工具完成工作。它会为您省去很多麻烦和几个小时!

【讨论】:

这就是我要找的。使用 pm2 解决方案,以后有没有办法给它附加一个终端? @Quantumplation,没有。这是不可能的,因为该进程没有在交互式会话中运行。但是你可以通过tail -fing pm2 生成的日志文件有同样的“感觉”。 您指定了许多人发现的screen 解决方案,这是一种解决方法。有很多方法可以完成特定任务。我相信碰巧(考虑具体问题)它恰好实现了run as background and never die 对许多人来说非常出色的具体任务。它还具有额外的好处,即允许用户返回其中重新交互并根据需要进行更改。关键是组件是backgroundnever die。所有的解决方案都有一定的好处。 @Rakshith Ravi - 我不同意。这些都需要额外的下载/软件/工具(除了初始化解决方案,没有给出解决方案)。 nohup 解决方案。它已融入 Linux,这就是它的用途。这是一条线,它很干净,并且每次都按预期工作,无论更新如何。人们真的应该尽量避免将第三方工具用于此类基本用例。 docker 示例(例如)比投票最多的答案中的一个简单命令更加冗长和资源密集。喜欢 Docker,但不是为了这个。 @Jack_Hu,我对开销毫无疑问,但nohup 解决方案不满足“永不消亡”的要求。除非你写了一个非常棘手的trap 或一个骇人听闻的无限循环,否则我看不出如何在不使用专门为此目的编写的工具(或者当然是你自己编写的 init 脚本)的情况下保持进程的守护进程。【参考方案5】:

另一种解决方案不承认这项工作

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

【讨论】:

disown 正是我想要的,但 -h 标志有什么作用?我在手册中找不到它 来自手册页:如果给出了 -h 选项,则不会从表中删除每个作业规范,但会进行标记,以便在 shell 接收到 SIGHUP 时不会将 SIGHUP 发送到作业。如果没有提供作业规范,-a 选项表示删除或标记所有作业;【参考方案6】:

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

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

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

【讨论】:

【参考方案7】:

Nohup 和 screen 为在后台运行 Node.js 提供了出色的轻量级解决方案。 Node.js 进程管理器 (PM2) 是一个方便的部署工具。在你的系统上使用 npm 全局安装它:

npm install pm2 -g

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

pm2 start app.js

您可以选择将其链接到 Keymetrics.io Unitech 制造的监控 SAAS。

【讨论】:

【参考方案8】:
$ disown node server.js &

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

【讨论】:

【参考方案9】:

根据@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"

【讨论】:

【参考方案10】:

你读过nohup命令吗?

【讨论】:

【参考方案11】:

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

复制骨架脚本并根据您的需要对其进行调整,可能您所要做的就是设置一些变量。您的脚本将从/lib/init/init-d-script 继承良好的默认值,如果某些内容不符合您的需要 - 在您的脚本中覆盖它。如果出现问题,您可以在源代码/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

除了设置变量之外,我还必须覆盖 do_stop_cmd,因为 python 替换了可执行文件,所以服务没有正确停止。

【讨论】:

【参考方案12】:

除了上面很酷的解决方案之外,我还提到了 supervisord 和 monit 工具,它们允许启动进程、监控它的存在并在它死亡时启动它。使用“monit”,您还可以运行一些主动检查,例如检查进程是否响应 http 请求

【讨论】:

【参考方案13】:

对于 Ubuntu,我使用这个:

(exec PROG_SH &> /dev/null &)

问候

【讨论】:

次要点:如果 PROG_SH 是可执行文件,则不需要 'exec'。 David 提出的解决方案的重点是使孩子与当前正在运行的 shell 分离。 child 的 parent 变为 'pid 1' 并且在 shell 终止时不会受到影响。【参考方案14】:

试试这个简单的解决方案

cmd & 退出

【讨论】:

以上是关于如何将 Node.js 作为后台进程运行并且永不死亡?的主要内容,如果未能解决你的问题,请参考以下文章

如何将 node.js 服务器作为守护进程启动?

发送响应后如何在node.js api中运行后台任务?

Node.js部署到服务器之后台守护进程管理器Forever

如何将 node.js 模块作为 node.js 程序的子进程执行?

forever让node.js持久运行

Node.js 工作者/后台进程