NodeJS React Systemd 服务不起作用

NodeJS React Systemd 服务不起作用

我正在尝试为一个简单的 React 应用程序设置一个 systemd 服务。此应用程序托管在 /home/myuser/test 中。npm 和 node 都在 PATH 中,并硬链接到 /usr/bin。所有文件都具有 myuser:myuser 用户和组的权限。如果我手动启动它,npm start它会正确启动并从http://localhost:3000

    Compiled successfully!

You can now view test in the browser.

  Local:            http://localhost:3000
  On Your Network:  http://myipaddress:3000

Note that the development build is not optimized.
To create a production build, use npm run build.

如果我尝试通过 systemd 启动应用程序,它会失败,但不会说明原因。我从同一路径、使用同一用户启动它,并尝试了 ExecStart 可以想象到的所有组合:

ExecStart=npm start
ExecStart=/usr/bin/npm start
ExecStart=/usr/bin/node /home/myuser/test/node_modules/react-scripts/scripts/start.js

它们都产生相同的结果,即它“启动”正常,但不久之后就失败了,而且在 journalctl 中显然没有任何原因:

 $sudo systemctl status node-client   
 ● node-client.service - Node-React Frontend Server
   Loaded: loaded (/etc/systemd/system/node-client.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2020-04-08 09:46:10 UTC; 679ms ago
 Main PID: 18165 (node)
   CGroup: /system.slice/node-client.service
           └─18165 /usr/bin/node /home/myuser/test/node_modules/react-scripts/scripts/start.js

Apr 08 09:46:10 hostname systemd[1]: Started Node-React Frontend Server.
Apr 08 09:46:10 hostname systemd[1]: Starting Node-React Frontend Server...

几秒钟后……

$sudo systemctl status node-client
● node-client.service - Node-React Frontend Server
   Loaded: loaded (/etc/systemd/system/node-client.service; disabled; vendor preset: disabled)
   Active: activating (auto-restart) since Wed 2020-04-08 09:46:00 UTC; 3s ago
  Process: 18142 ExecStart=/usr/bin/node /home/ec2-user/test/node_modules/react-scripts/scripts/start.js (code=exited, status=0/SUCCESS)
 Main PID: 18142 (code=exited, status=0/SUCCESS)

我在 journalctl 上不断收到以下信息

    -- Logs begin at Tue 2020-03-17 15:04:59 UTC, end at Wed 2020-04-08 09:48:23 UTC. --
Apr 08 09:48:22 hostname systemd[1]: Starting Node-React Frontend Server...
Apr 08 09:48:22 hostname systemd[1]: Started Node-React Frontend Server.
Apr 08 09:48:22 hostname systemd[1]: node-client.service holdoff time over, scheduling restart.
Apr 08 09:48:12 hostname nodeclient[18390]: Starting the development server...
Apr 08 09:48:12 hostname nodeclient[18390]: ℹ 「wds」: 404s will fallback to /
Apr 08 09:48:12 hostname nodeclient[18390]: ℹ 「wds」: Content not from webpack is served from /home/myuser/test/public
Apr 08 09:48:12 hostname nodeclient[18390]: ℹ 「wds」: webpack output is served from
Apr 08 09:48:12 hostname nodeclient[18390]: ℹ 「wds」: Project is running at http://myipaddress/
Apr 08 09:48:10 hostname systemd[1]: Starting Node-React Frontend Server...
Apr 08 09:48:10 hostname systemd[1]: Started Node-React Frontend Server.
Apr 08 09:48:10 hostname systemd[1]: node-client.service holdoff time over, scheduling restart.
Apr 08 09:48:00 hostname nodeclient[18368]: Starting the development server...
Apr 08 09:48:00 hostname nodeclient[18368]: ℹ 「wds」: 404s will fallback to /
Apr 08 09:48:00 hostname nodeclient[18368]: ℹ 「wds」: Content not from webpack is served from /home/myuser/test/public
Apr 08 09:48:00 hostname nodeclient[18368]: ℹ 「wds」: webpack output is served from
Apr 08 09:48:00 hosntame nodeclient[18368]: ℹ 「wds」: Project is running at http://myipaddress/

systemd 服务文件随着时间的推移而发生变化,但无论 ExecStart 和其他变化如何,错误都是相同的,这是截至目前的内容:

[Unit]
Description=Node-React Frontend Server
After=syslog.target network.target

[Service]
ExecStart=/usr/bin/node node_modules/react-scripts/scripts/start.js
Restart=always
RestartSec=10s
TimeoutSec=900
User=myuser
Group=myuser
Environment=PATH=/usr/bin:/usr/local/bin
WorkingDirectory=/home/myuser/test/
StandardOutput=syslog
StandardError=syslog
SyslogIdentifier=nodeclient

[Install]
WantedBy=multi-user.target

操作系统是 Centos7。所有测试均使用同一用户、无 sudo、手动和通过 systemd 执行相同命令完成。手动启动有效,但 systemd 无效。

最后,需要说明的是,我通过 systemd 拥有 Express-NodeJS 应用程序,并且它使用相同的 systemd 配置正确启动。只有 React 会失败。

任何帮助将不胜感激!

谢谢

尼西

答案1

升级后我遇到了同样的问题,我的 systemd 服务每次启动时都会以错误代码 0 退出。

这是由于 2 月份对 react-scripts start.js 的更新所致

Kolega 的答案确实是解决这个问题的最佳方法:

将 CI(持续集成)环境变量设置为 true。可以在服务文件中使用以下命令完成此操作:

Environment=CI=true

以下是示例 .service 文件:

# Sample - My Sample Service file
[Unit]
Description=Sample - Sample Service to start a React server
After=network.target

[Service]
Type=simple
ExecStart=/usr/bin/npm start --prefix /home/pi/sample
Environment=CI=true
WorkingDirectory=/home/pi/sample
StandardOutput=inherit
StandardError=inherit
Restart=no
User=pi

[Install]
WantedBy=multi-user.target

如果以上方法对您有用,请对 Kolega 的回答投赞成票。

我原来的解决方案如下,这需要对反应分发文件进行更改:

为了解决这个问题,我注释掉了使 start.js 在 stdin 结束时退出的更改。由于服务没有 stdin 输入,因此它在应用程序启动之前就存在了。这在 node-modules/react-scripts/scripts/start.js 中

    if (isInteractive || process.env.CI !== 'true') {
      // Gracefully exit when stdin ends
      // process.stdin.on('end', function() {
      //   devServer.close();
      //   process.exit();
      // });
      process.stdin.resume();
    }

start.js 在 stdin 结束时退出的更改记录在https://github.com/facebook/create-react-app/pull/7203/files/108bafe5d5b85c9544dd05b5ed42b4e90c66b2ca

答案2

我通过将以下内容添加到我的 .service 文件的 [Service] 部分来解决这个问题:

标准输入=tty-force

答案3

如果您想要拥有非退出服务,则npm start必须定义一个CI变量以防止在读取后退出EOF。此解决方案也可以在用户会话中运行。我的服务文件中的重要部分是Environment=CI=True

[Unit]
Description=Project

[Service]
ExecStart=/usr/bin/npm run start --prefix /home/ondrej/project
Environment=CI=true

[Install]
WantedBy=default.target

相关内容