5

I am trying to set up a systemd service for a simple react application. This application is hosted in /home/myuser/test. Both npm and node are in the PATH and hard linked to /usr/bin. All the files have permissions for the myuser:myuser user and group. If I launch this manually with npm start it launches correctly and serves the app from 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.

If I try to launch the application through systemd, it fails but does not specify why. I am launching it from same path, with the same user, and have tried all combinations imaginable for ExecStart:

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

They all produce the same result, namely, it "starts" ok, and soon after it just fails, with no reason for it apparently in 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...

And a few seconds later...

$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)

I keep getting the following on 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/

The systemd service file has changed over time but the error has been the same regardless of the ExecStart and other changes, this is the contents as of now:

[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

The OS is Centos7. All the tests have been done with the same user, no sudo, same commands both manually and through systemd. Manual launch works, systemd doesn't.

Lastly, to mention, I have Express-NodeJS application through systemd and it is launching correctly, with the same systemd configuration. It only fails for React.

Any help would be greatly appreciated!

Thanks

Nissy

Nissy A.W.
  • 132
  • 1
  • 8

3 Answers3

4

I encountered the same problem after an upgrade, my systemd service started exiting with error code 0 every time it was started.

This is due to a February update to react-scripts start.js

Kolega's answer is really the best approach to resolve this:

Set the CI (Continuous Integration) environment variable to true. This can be done in the service file with:

Environment=CI=true

Here is a sample .service file:

# 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

Please up-vote Kolega's answer if the above works for you.

My original solution is below, which requires making changes to react distribution files:

To resolve this I commented out the change that makes start.js exit when stdin ends. Since with a service there is no stdin input, it exists before the App starts. This is in 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();
    }

The start.js change to exit when stdin ends is documented in https://github.com/facebook/create-react-app/pull/7203/files/108bafe5d5b85c9544dd05b5ed42b4e90c66b2ca

lzb
  • 56
  • 5
  • Thanks a ton! I was puzzled as all the other nodejs services worked just fine, just failed with React. – Nissy A.W. Apr 08 '20 at 14:35
  • Many thanks, this solved my problem too. – jamboNum5 Jul 06 '20 at 09:25
  • Should this be considered a bug in the `start.js` script? – mmw Aug 12 '20 at 14:46
  • Yes, it is not properly identifying and handling non-interactive processes. Thanks for the edit! – lzb Aug 13 '20 at 22:22
  • I think this is not a good solution, changing distribution files is a bad practice – Ondřej Kolín Jan 07 '21 at 09:17
  • I agree with @KOLEGA, the Environment approach is much better than editing a distribution file. Are there any consequences to setting CI for npm start? I see CI turns warnings to errors in build, but I don't see how that could impact this. I haven't found any issues with setting CI in my testing. – lzb Jan 08 '21 at 22:35
3

I solved this by adding the following to the [Service] section of my .service file:

StandardInput=tty-force

1

If you want to have non-exiting service, with npm start you have to define a CI variable which prevents quitting after reading EOF. This solution can be run in users session as well. The important part from my service file is Environment=CI=True.

[Unit]
Description=Project

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

[Install]
WantedBy=default.target
Ondřej Kolín
  • 121
  • 1
  • 4