2

I am trying to run a node app on boot. The script runs ok from the command line, I can stop and start it but when I try to do it on boot I get an error as if the script were reading the node_app.js line by line.

Here is my script my_node_server:

#! /bin/bash

### BEGIN INIT INFO
# Provides:          skeleton
# Required-Start:    $remote_fs $syslog
# Required-Stop:     $remote_fs $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: Example initscript
# Description:       This file should be used to construct scripts to be
#                    placed in /etc/init.d.
### END INIT INFO


# Some things that run always

APP_DIR="/home/pi/node_app_folder"

NODE_APP="node_app.js"

LOG_FILE="/home/pi/my_node_server.log"

PID_FILE="/home/pi/my_node_server.pid"

NODE_EXEC=$(which node)


# Carry out specific functions when asked to by the system
case "$1" in
  start)
    echo "Starting script my_node_server "
    echo "Check log in /home/pi/my_node_server.log"

    echo "" > "$LOG_FILE"
    echo "" > "$PID_FILE"

    "$NODE_EXEC" "$APP_DIR/$NODE_APP" > "$LOG_FILE" 2>&1 &

    echo $! > "$PID_FILE"
    echo  "my_node_server is working with pid: $(cat $PID_FILE)" | tee "$LOG_FILE"
    echo "Check pid in /home/pi/my_node_server.pid"
    ;;
  stop)
    echo "Stopping script my_node_server" | tee -a "$LOG_FILE"
    PID="$(cat "$PID_FILE")"
    echo killing PID: "$PID"
    kill "$PID"
    ;;
  *)
    echo "Usage: /etc/init.d/my_node_server {start|stop}"
    exit 1
    ;;
esac

exit 0

It also works on the command line, from both pi and root users:

APP_DIR="/home/pi/node_app_folder"

NODE_APP="node_app.js"

NODE_PROGRAM=$(which node)

"$NODE_PROGRAM" "$APP_DIR/$NODE_APP" 2>&1

Why does it not do it at boot time? I have done:

sudo update-rc.d my_node_server defaults

By the way my shell is bash:

$ echo $0
/bin/bash

If I replace

"$NODE_EXEC" "$APP_DIR/$NODE_APP" > "$LOG_FILE" 2>&1 &

for

/home/pi/my-node-dir/bin/node /home/pi/node_app.js > "$LOG_FILE" 2>&1 &

it works ok.

So, what am I missing?

2

You could confirm this by logging the value of $NODE_EXEC somewhere, but I think it is probably not what you think it is.

NODE_EXEC=$(which node)

It certainly won't be /home/pi/my-node-dir/bin/node, because that path isn't in $PATH. If there's a node in $PATH, it would use that. If there isn't, that variable will be "which: no node in (...)".

You could add to path at beginning:

PATH=$PATH:/home/pi/my-node-dir/bin

Or you could just hardcode $NODE_EXEC to the value you actually want.

  • Of course /home/pi/my-node-dir/bin is in my $PATH, otherwise it wouldn't run from the cli. And it is in the $PATH for pi user and root user as well. $ which node produces /home/pi/my-node-dir/bin/node – gugol Jun 4 '15 at 13:37
  • 1
    It's not in $PATH when that script is run by init, unless you've specifically configured the system to put it there. Again, these are things you could check very simply by just logging the values to a file to confirm they are what you think they are. This is basic debugging 101. If you can't be bothered to do that, there is no help anyone can give you. – goldilocks Jun 4 '15 at 13:41
  • 2
    The point here is: $PATH is not set to include your local path by the time init runs the script, so you cannot rely on which node to find node. You need to either put node in a directory that is in a default available path (/opt/bin perhaps?) or explicitly put the path to node in your script. – Phil B. Jun 4 '15 at 14:35
  • 1
    As @goldilocks and Phil_B remarked at boot time the $PATH variable hasn't been set yet. In the end I hardcoded the $NODE_EXEC variable to my node installation path. – gugol Jun 4 '15 at 15:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.