如何在AWS上的Amazon Linux AMI中自动启动node.js应用程序?

50

有没有一个简要指南来解释如何在实例启动和运行时启动应用程序?如果它是通过 yum 安装的其中一项服务,那么我想我可以使用 /sbin/chkconfig 将其添加到服务中。(为确保正确性,这样做对吗?)

然而,我只想运行未通过 yum 安装的程序。要运行 node.js 程序,我必须在每次系统启动时在主目录下运行脚本 sudo node app.js

我不习惯 Amazon Linux AMI,因此我在寻找在每次启动时自动运行某些脚本的“正确”方法方面遇到了一些麻烦。

是否有一种优雅的方式来实现这个目标?


尝试这个解决方案。它非常简单。https://dev59.com/_mYr5IYBdhLWcg3wy9KA#22171598 - Vince Yuan
尝试使用pm2。它优雅、适用于生产环境,且简单易用。在2022年对Node应用程序非常有效。 - Naveen Kumar
8个回答

24

一种方法是创建一个Upstart作业。这样,当Linux加载时,您的应用程序将启动,如果它崩溃,将自动重新启动,并且您可以通过sudo start yourapp/sudo stop yourapp/sudo restart yourapp来启动/停止/重启它。

以下是开始的步骤:

1)安装Upstart实用程序(如果使用标准的Amazon Linux AMI,则可能预先安装):

sudo yum install upstart

对于 Ubuntu:

sudo apt-get install upstart

2)为您的节点应用程序创建upstart脚本:

/etc/init中添加文件yourappname.conf,其中包含以下代码行:

#!upstart
description "your app name"

start on started mountall
stop on shutdown

# Automatically Respawn:
respawn
respawn limit 99 5

env NODE_ENV=development

# Warning: this runs node as root user, which is a security risk
# in many scenarios, but upstart-ing a process as a non-root user
# is outside the scope of this question
exec node /path_to_your_app/app.js >> /var/log/yourappname.log 2>&1

3) 使用sudo start yourappname来启动您的应用程序。


13
据我所知,Amazon上运行的Linux是基于RedHat而非Ubuntu的,因此我认为upstart不可用。 - Unknown
5
在AWS上: sudo yum install upstart - Dave Munger
1
sudo: start: command not found,我猜Ubuntu已经转换到systemd了? - bvdb
我尝试了这个解决方案,并且在SSH手动启动时它可以工作,但是当我重新启动我的镜像时它不会自动启动。我以为它会在重启时启动,难道不是这样吗? - Jackie
2
upstart已被移除 :( - Tarwin Stroh-Spijer
显示剩余2条评论

12

您可以使用 forever-service 将 Node 脚本提供为服务,并在启动时自动启动。以下命令将完成必要的操作:

npm install -g forever-service
forever-service install test

此命令将使用forever在当前目录中将app.js设置为服务。该服务会在每次系统重启时自动重新启动。同时,停止服务时也会尝试优雅地关闭服务。此脚本还将配置logrotate脚本。

Github网址:https://github.com/zapty/forever-service

截至目前,forever-service支持Amazon Linux、CentOS和Redhat,其他Linux发行版、Mac和Windows的支持正在进行中。

注意:我是forever-service的作者。


如何在启动时启动任何应用程序,而无需在实例中编写代码。谢谢! - Sebastien H.
2
这个不起作用,出现了“forever-service必须以root身份运行”的错误提示。尝试使用命令“sudo forever-service install test”,但Amazon Linux响应“sudo: forever-service: command not found”。 - jdog

7
我的Amazon Linux实例运行在Ubuntu上,我使用systemd进行设置。
首先,您需要创建一个<servicename>.service文件(在我的情况下是cloudyleela.service)。
sudo nano /lib/systemd/system/cloudyleela.service

在这个文件中输入以下内容:
[Unit]
Description=cloudy leela
Documentation=http://documentation.domain.com
After=network.target

[Service]
Type=simple
TimeoutSec=0
User=ubuntu
ExecStart=/usr/bin/node /home/ubuntu/server.js
Restart=on-failure

[Install]
WantedBy=multi-user.target

在这个应用程序中,node应用程序已经启动。你需要提供完整的路径。我已经配置好应用程序如果出现错误,则应该简单地重新启动。亚马逊使用的实例默认情况下没有密码。
从磁盘重新加载文件,然后你就可以启动你的服务。你需要启用它才能让它作为一个服务处于激活状态,并在启动时自动启动。
ubuntu@ip-172-31-21-195:~$ sudo systemctl daemon-reload
ubuntu@ip-172-31-21-195:~$ sudo systemctl start cloudyleela
ubuntu@ip-172-31-21-195:~$ sudo systemctl enable cloudyleela
Created symlink /etc/systemd/system/multi-user.target.wants/cloudyleela.service → /lib/systemd/system/cloudyleela.service.
ubuntu@ip-172-31-21-195:~$

这里提供了一份关于node.js systemd的教程,可以在这里查看。

如果你运行一个Web服务器:

你可能会遇到在80端口上运行Web服务器的问题。最简单的解决方案是在不同的端口上(比如4200)运行Web服务器,然后将该端口重定向到80端口。您可以通过以下命令实现此操作:

sudo iptables -t nat -A PREROUTING -i -p tcp --dport 80 -j REDIRECT --to-port 4200

很遗憾,这种方法不是持久的,因此每次服务器重新启动时都需要重复执行。更好的方法是在服务脚本中包含以下命令:
  1. ExecStartPre 添加端口转发
  2. ExecStopPost 删除端口转发
  3. PermissionStartOnly 使用sudo权限执行
因此,可以像这样操作:
[Service]
...
PermissionsStartOnly=true
ExecStartPre=/sbin/iptables -t nat -A PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4200
ExecStopPost=/sbin/iptables -t nat -D PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 4200

不要忘记重新加载和重启您的服务:

[ec2-user@ip-172-31-39-212 system]$ sudo systemctl daemon-reload
[ec2-user@ip-172-31-39-212 system]$ sudo systemctl stop cloudyleela
[ec2-user@ip-172-31-39-212 system]$ sudo systemctl start cloudyleela
[ec2-user@ip-172-31-39-212 system]$

针对微服务 (2020年12月更新)

之前提到的解决方案具有很大的灵活性,但需要一些时间来设置。每增加一个应用程序,都需要重新进行整个流程。当您要安装第五个节点应用程序时,您肯定会开始想:"肯定有捷径"

PM2的优点在于只需安装1个服务。接下来是由PM2管理实际应用程序。

即使是PM2的初始设置也很容易,因为它会自动为您安装pm2服务。

npm install pm2 -g

添加新服务甚至更容易:

pm2 start index.js --name "foo"`. 

当所有设定都完成并运行正常后,您可以保存设置,以便在重新启动时自动启动。
pm2 save

如果您想了解所有正在运行的节点应用程序的概述,可以运行pm2 list。PM2还提供了一个在线(基于Web)的仪表板,以远程监视您的应用程序。但是,您可能需要许可证才能访问某些仪表板功能(价格有点过高,个人认为)。

请注意,PermissionsStartOnly已被更灵活的“+”、“!”和“!!”前缀所代替,用于ExecStart=和其他命令。相关问题:https://superuser.com/questions/1504114/permissionsstartonly-alternative-in-systemd - brillout

6
您可以通过在/etc/rc.local中添加您的命令来启动应用程序,这是一个快速的解决方案。
但是,如果您想采用更加优雅的方式,您需要将应用程序打包成一个rpm文件,并编写一个启动脚本放置在/etc/rc.d中,以便您可以在应用程序上使用chkconfig命令,然后安装该rpm文件到您的实例中。
您可以参考此链接此链接进行了解(或者直接在谷歌上搜索“创建rpm包”)。

如果我使用rpm方法,每次修改应用程序时都必须重新构建rpm包吗? - user482594
是的,应用程序中的更改意味着创建和重新部署新的 .rpm,就像使用 yum 更新常规软件包一样。 - Unknown
4
不需要创建RPM文件-你可以使用init脚本和chkconfig而不必创建RPM。 - TomG
1
当您打开rc.local时,您会看到一个大警告,告诉您它已被弃用,并且现在的首选方法是:systemd-->请参见我的答案。 :) - bvdb

5
您可以创建一个脚本,可以启动和停止您的应用程序,并将其放置在 /etc/init.d 中;使脚本遵循 chkconfig 的约定(如下),然后使用 chkconfig 将其设置为在启动其他服务时启动。

您可以从 /etc/init.d 中选择现有脚本作为示例;this article 描述了要求,基本上是:

  • 可执行脚本,标识所需的 shell(即 #!/bin/bash)
  • 形式为 # chkconfig: 的注释,其中 通常为 345,startprio 表示在启动服务的顺序中的位置,而 stopprio 则表示在停止服务的顺序中的位置。我通常选择已经存在的类似服务,并将其用作这些值的指南(例如,如果您有一个与 Web 相关的服务,请从与 httpd 相同的级别开始,并具有类似的启动和停止优先级)。

设置好您的脚本后,您可以使用

 chkconfig --add yourscript 
 chkconfig yourscript on 

然后你就可以愉快地进行了。 (某些发行版可能需要您手动将符号链接到/etc/init.d/rc.d脚本,但我相信启用该脚本时,您的AWS发行版会为您执行此操作。


-1

使用 Elastic Beanstalk :) 它提供自动扩展、SSL 终止、蓝绿部署等支持。

如果你想要在基于 RedHat 的 Linux 发行版上(Amazon Linux 是 RedHat 的一个变种)采用咸鱼系统管理员的方式,可以学习 @bvdb 在上面回答中提到的 systemd

https://en.wikipedia.org/wiki/Systemd

按照EC2实例上的说明设置所有内容,快照自定义AMI,并将此自定义AMI用作托管应用程序的EC2实例的基础。这样您就不必多次完成所有设置。如果在具有正常运行时间要求的生产环境中运行,则可能还需要熟悉负载平衡器。

或者,正如@bvdb所提到的那样,您也可以使用pm2systemd进行接口交互。虽然我认为pm2无法帮助您在多个EC2实例上运行应用程序,但绝对建议在具有正常运行时间要求的生产环境中这样做。

所有这些都是一个非常陡峭的学习曲线。由于OP似乎对所有这些都很新,因此Elastic Beanstalk,Google App Engine和其他工具是在云中运行代码的好方法,而无需考虑所有这些。

现在我使用TypeScript进行开发,针对大多数事情部署到云中的无服务器函数执行,完全不必考虑包安装或应用程序启动。


-2

你可以使用 screen。运行 crontab -e 并添加以下行:

@reboot  screen -d -m bash -c "cd /home/user/yourapp/; node app"

-12
一直在AWS上使用forever,它的表现不错。安装方法如下:
 [sudo] npm install forever -g

添加应用程序,请使用

 forever start path_to_application

停止应用程序使用

 forever stop path_to_application

这篇文章对我设置它非常有帮助。


但是我需要在每次启动时运行 forever 节点模块吗? - user482594
1
不,永远不会在每次启动时开始。 - Anthony Webb
3
很抱歉,但这并没有回答问题 - 尽管它是图片的一部分。如果您能解释如何在启动时运行Forever,那么我会改为+1。 - iandotkelly
2
要在重启时通过forever运行脚本,可以使用crontab: $ crontab -u user -e 并添加 @reboot /usr/lib/node_modules/forever/bin/forever start /user/script.js - guido
@guido 我的forever在不同的地方。./.nvm/versions/node/v6.11.5/bin/forever - jdog
显示剩余2条评论

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