如何永久使用节点应用程序作为systemd服务?

问题描述 投票:1回答:1

我是Node的新手,并关注Ryan Lewis出色的AWS Developer教程。在该课程中,我们将学习使用来自AWS Marketplace的Bitnami Node.js映像将Node.js应用程序部署到AWS EC2。为了进行一些练习,我想使用systemd将应用程序转换为服务,以便在重新启动后将其恢复。但是,经过大量调试后,我发现该服务似乎一直在重新启动,并且该应用程序从未上线。这可能是由应用程序的启动方式引起的。它使用forever CLI工具运行。手动运行npm start时,看到以下输出:

npm start

> [email protected] prestart /home/bitnami/hamstercourse
> npm run build


> [email protected] build /home/bitnami/hamstercourse
> webpack

(node:19917) DeprecationWarning: Chunk.modules is deprecated. Use Chunk.getNumberOfModules/mapModules/forEachModule/containsModule instead.
Hash: aa4bec1a367d114f2c7f
Version: webpack 3.3.0
Time: 12349ms
             Asset     Size  Chunks                    Chunk Names
application.min.js   363 kB       0  [emitted]  [big]  application
    stylesheet.css  13.4 kB       0  [emitted]         application
  [10] ./node_modules/react-redux/es/index.js + 14 modules 37.6 kB {0} [built]
  [18] ./node_modules/react-router-dom/es/index.js + 13 modules 11.9 kB {0} [built]
  [59] ./node_modules/redux/es/index.js + 6 modules 21.3 kB {0} [built]
  [62] ./node_modules/react-router-redux/es/index.js + 4 modules 5.87 kB {0} [built]
 [105] ./app/index.jsx 1.86 kB {0} [built]
 [209] ./app/router.jsx 2.85 kB {0} [built]
 [211] ./app/routes/index.jsx 1.65 kB {0} [built]
 [287] ./app/reducers/index.js 316 bytes {0} [built]
 [288] ./app/reducers/hamsters.js 717 bytes {0} [built]
 [289] ./app/reducers/races.js 649 bytes {0} [built]
 [290] ./app/reducers/user.js 2.32 kB {0} [built]
 [291] ./app/reducers/leaderboards.js 355 bytes {0} [built]
 [292] ./app/reducers/status.js 285 bytes {0} [built]
 [293] ./app/index.less 41 bytes {0} [built]
 [326] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/index.less 247 bytes [built]
    + 312 hidden modules
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/index.less 247 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Config/index.less 485 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/User/index.less 275 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Leaderboards/index.less 485 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Races/index.less 485 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Race/index.less 485 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Main/index.less 501 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Login/index.less 488 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Hamster/index.less 485 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Hamsters/index.less 617 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       [0] ./node_modules/css-loader?modules&importLoaders=1&localIdentName=[name]__[local]___[hash:base64:5]!./node_modules/less-loader/dist!./app/scenes/Main/Hero/index.less 827 bytes {0} [built]
        + 1 hidden module
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules
Child extract-text-webpack-plugin:
       2 modules

> [email protected] start /home/bitnami/hamstercourse
> forever stopall && ./node_modules/.bin/forever start index.js

info:    No forever processes running
warn:    --minUptime not set. Defaulting to: 1000ms
warn:    --spinSleepTime not set. Your script will exit if it does not stay up for at least 1000ms
info:    Forever processing file: index.js

然后该过程转到后台,并且可以使用forever listforever stop等进行管理。如here所述,systemd杀死了后台进程(并且有充分的理由)。

为了证实我的怀疑,我尝试过这样运行服务:

[Unit]
Description=Node.js Hamster Http Server

[Service]
PIDFile=~/hamster-99.pid
User=bitnami
Group=bitnami
Restart=always
RestartSec=10
StandardOutput=syslog
StandardError=syslog
KillSignal=SIGQUIT
WorkingDirectory=/home/bitnami/hamstercourse
ExecStart=/opt/bitnami/nodejs/bin/node /home/bitnami/hamstercourse/index.js

[Install]
WantedBy=multi-user.target

并且在启用服务并重新加载守护进程之后,输出为:

hamster.service - Node.js Hamster Http Server
   Loaded: loaded (/etc/systemd/system/hamster.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2019-06-26 10:57:46 UTC; 28min ago
 Main PID: 19847 (.node.bin)
    Tasks: 11
   Memory: 26.8M
      CPU: 2.019s
   CGroup: /system.slice/hamster.service
           +-19847 /opt/bitnami/nodejs/bin/.node.bin /home/bitnami/hamstercourse/index.js

Jun 26 10:57:46 ip-172-31-35-115 systemd[1]: hamster.service: Main process exited, code=dumped, status=3/QUIT
Jun 26 10:57:46 ip-172-31-35-115 systemd[1]: Stopped Node.js Hamster Http Server.
Jun 26 10:57:46 ip-172-31-35-115 systemd[1]: hamster.service: Unit entered failed state.
Jun 26 10:57:46 ip-172-31-35-115 systemd[1]: hamster.service: Failed with result 'core-dump'.
Jun 26 10:57:46 ip-172-31-35-115 systemd[1]: Started Node.js Hamster Http Server.
Jun 26 10:57:48 ip-172-31-35-115 node[19847]: Server started at http://localhost:3000

因此,好消息是:这实际上在运行服务。欢呼!但是,它跳过了npm start实际运行的许多基本步骤(如缩小应用程序),并且当然不会通过forever运行应用程序。可以讨论在作为服务运行时是否需要使用像forever这样的管理工具,但是应该可以在不更改应用程序的情况下从systemd运行它,对吗?那我该怎么办呢?

更新:

我刚刚找到https://unix.stackexchange.com/questions/308311/systemd-service-runs-without-exiting,并尝试在单位文件中使用Type=forking。这实际上似乎起作用。但这是路吗?还是还有另一种最佳做法?

node.js systemd forever
1个回答
0
投票
https://www.freedesktop.org/software/systemd/man/systemd.service.html

如果设置为分叉,则预期该进程配置为ExecStart =将在启动过程中调用fork()。父母当启动完成并且所有建立了沟通渠道。孩子继续奔跑主要服务流程,服务经理将考虑该单元父进程退出时启动。这是行为传统的UNIX服务。如果使用此设置,建议也使用PIDFile =选项,以便systemd可以可靠地识别服务的主要过程。 systemd将继续启动父流程退出后立即跟进。

这就是forever的工作方式。另请注意,apache2服务也使用Type=forking
© www.soinside.com 2019 - 2024. All rights reserved.