简体   繁体   中英

Cannot find out what's wrong with my service

I have a little node application. It works fine when I run

pi@rpb:/opt/linear-actuator $ /home/pi/.nvm/versions/node/v14.8.0/bin/npm start

I created a service to make sure it starts automatically on boot.

[Unit]
Description=LinearActuator
After=network.target

[Service]
WorkingDirectory=/opt/linear-actuator
ExecStart=/home/pi/.nvm/versions/node/v14.8.0/bin/npm start
Restart=always
User=pi
Environment=PORT=8081

[Install]
WantedBy=multi-user.target

But my service fails to start (I have enabled it before). journalctl says

août 27 21:37:16 rpb npm[1913]: > linearactuator@1.0.0 start /opt/linear-actuator
août 27 21:37:16 rpb npm[1913]: > node server.js
août 27 21:37:18 rpb npm[1913]: /opt/linear-actuator/server.js:4
août 27 21:37:18 rpb npm[1913]: import express from 'express';
août 27 21:37:18 rpb npm[1913]: ^^^^^^
août 27 21:37:18 rpb npm[1913]: SyntaxError: Unexpected token import

I had this error when running my app with an older version of node. But the absolute path used in my service is fine.

pi@rpb:/opt/linear-actuator $ which node
/home/pi/.nvm/versions/node/v14.8.0/bin/node
pi@rpb:/opt/linear-actuator $ node -v
v14.8.0
pi@rpb:/opt/linear-actuator $ which npm
/home/pi/.nvm/versions/node/v14.8.0/bin/npm
pi@rpb:/opt/linear-actuator $ npm -v
6.14.7

Any lighting on what I am missing ? :)

The import syntax is only valid for modules. You should rename the file from server.js to server.mjs .

The import syntax is only supported (without experimental flag) in Node 14 onwards. Based on your node and npm versions you printed, it does appear that you have Node 14+ installed using nvm. However, when your service is run, an older version of NodeJS is being picked up. Most probably something that you installed using the bundled package manager (apt?).

NVM doesn't store or link the node binaries in one of the standard linux binary locations (/usr/bin or /usr/local/bin). It however, adds some scripts in .profile or .bashrc (based on your terminal) to update the PATH env var with correct Node binary paths. Typically:

export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm

Now when your service is executed the systemd must be running your execStart command as is; without loading the .profile / .bashrc file, wherever the nvm script is executed from. If you don't plan to be changing versions of the node often, you could forget about nvm and just set the PATH env var in your service as the current $PATH from your terminal. Just run echo $PATH pick the result and paste is in the placeholder below.

[Unit]
Description=LinearActuator
After=network.target

[Service]
WorkingDirectory=/opt/linear-actuator
ExecStart=/home/pi/.nvm/versions/node/v14.8.0/bin/npm start
Restart=always
User=pi
Environment=PORT=8081
Environment=PATH=<Put the result of `echo $PATH` here>

[Install]
WantedBy=multi-user.target

A better approach would be to accomodate the nvm in your 'start command'. Basically create a new start-my-server.sh file, make is executable and add a series of commands something like this (change paths to suit your setup):

#!/bin/bash
[ -s "/home/pi/.nvm/nvm.sh" ] && \. "/home/pi/.nvm/nvm.sh"
cd /opt/linear-actuator
npm start

After this, point the execStart in your service to this newly created shell script instead of running npm start directly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM