Upstart script for node.js app
Asked Answered
H

2

11

I'm having trouble starting an Upstart script.

Here's the script (app.conf in /etc/init/)

description "node.js server"
author      "kvz"

start on startup
stop on shutdown

script
   # We found $HOME is needed. Without it, we ran into problems
   export HOME="/root"

   exec sudo -u /usr/local/bin/node \
                /var/www/vhosts/travelseguro.com/node/app.js \
                2>&1 >> /var/log/node.log
end script

When I run sudo start app, I get:

start: Unknown job: app

How can I make this work?

Helbonna answered 20/12, 2012 at 23:41 Comment(5)
I copied your script into /etc/init/app.conf and it worked for me (started a process and created the log file.) Are you sure the file is in the correct place with (ls -Al /etc/init/app.conf)? Also, what version of Upstart (start --version) and what OS?Capuano
Yes im sure its there.. Upstart 0.3.9 Ubuntu 8.04.4Helbonna
I used nodejitsu forever and it works very well i wanted upstart because i wanted to have it as a service its a simple very small client support chat so.. no big deal by using forever.Helbonna
Try a symlink in /etc/init.d something like ln -s /lib/init/upstart-job app.Oriya
You have to reload configuration info for upstart. Use "sudo initctl reload-configuration" for this. I wrote detailed answer belowNuno
C
16

I was having the same problem running on the latest Amazon (AWS) linux which is Redhat based.

I have my upstart file in /etc/init called node.conf and when I ran sudo start node I would get a similar error to you start: Unknown job: node.

It turns out that the job won't start if there's an error in your .conf file. So I started out by commenting out all the lines and slowly building up to find the error. The error message isn't very clear and makes it look like upstart can't find your conf file.

Tailing your '/var/log/messages' will help you debug as Upstart logs to there (It may be somewhere different on Ubuntu. Mine said init: /etc/init/node-upstart.conf:8: Unknown stanza which helped me get to the bottom of it. In my particular case I was declaring variables incorrectly.

See on AskUbuntu for a similar thread.

Here's my edited working script:

<!-- language: lang-sh -->
#!upstart
# using upstart http://upstart.ubuntu.com/getting-started.html and node forever  https://github.com/nodejitsu/forever/  
# to run server
# redhat has additional sudo restrictions, you must comment out 'Default requiretty' from /etc/sudoers
#startup monitoring script derived from https://mcmap.net/q/47757/-node-js-setup-for-easy-deployment-and-updating

description "node.js server"
author      "jujhar"
env PROGRAM_NAME="node"
env FULL_PATH="/home/httpd/buto-middleman/public"
env FILE_NAME="forever.js"
env NODE_PATH="/usr/local/bin/node"
env USERNAME="springloops"

start on startup
stop on shutdown

script
    export HOME="/root"  
    export NODE_ENV=staging #development/staging/production

    echo $$ > /var/run/$PROGRAM_NAME.pid
    cd $FULL_PATH        
    #exec sudo -u $USERNAME $NODE_PATH $FULL_PATH/$FILE_NAME >> /var/log/$PROGRAM_NAME.sys.log 2>&1
    exec $NODE_PATH $FULL_PATH/$FILE_NAME >> /var/log/$PROGRAM_NAME.sys.log 2>&1
end script

pre-start script
    # Date format same as (new Date()).toISOString() for consistency
    echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Starting" >> /var/log/$PROGRAM_NAME.sys.log
end script

pre-stop script
    rm /var/run/$PROGRAM_NAME.pid
    echo "[`date -u +%Y-%m-%dT%T.%3NZ`] (sys) Stopping" >> /var/log/$PROGRAM_NAME.sys.log
end script

-- Edit 2013-06-01 --

If you're on Centos or Amazon Linux like me, take a look at this init.d script.

-- Edit 2013-10-14 --

Here's a link to a gist of an init.d script that I actually use in production on Amazon Linux(Redhat Based). I simply keep it in my project under an init.d folder and then symlink to it in the /etc/init.d folder and now it's a daemon/service!

-- Edit 2014-06-05 --

Check out this awesome blog artcile by Jeff Dickey on Node.js in production using systemd which is much cleaner and easier than all the stuff we've been doing here (IMHO). He also uses Ansible to control his cluster (which I love) but you don't have to go that far if you're not ready.

Contamination answered 25/3, 2013 at 13:2 Comment(1)
Your code doesn't allow to run the app under unprivileged user (your code doesn't work). See my working example below. It doesn't make any sense to use systemd on Ubuntu. Upstart allows to do whatever you need include delays a start of node.js until mongodb or other services will be started.Nuno
N
7

After a few attempts I implemented working .conf file for upstart which works as a service with automatic start after reboot and restart (respawn) in case of crash. Also it can start my app with unprivileged user permissions. The name of the file is /etc/init/my-app.conf.

To start / stop service please use

sudo start my-app / sudo stop my-app

If you have an error like

start: Unknown job: my-app

exec the following command

sudo initctl reload-configuration

My /etc/init/my-app.conf file:

#my-app                                                                           
description "node.js my-app website"                                                  
env FULL_PATH="/home/myuser/app.prod/app"                                              
env NODE_PATH="/usr/bin/node"                                                     


start on filesystem or runlevel [2345]                                            
stop on [!2345]                                                                   

script                                                                            
    export HOME="/root"                                                           
    export NODE_ENV=production                                                    
    echo $$ > /var/run/my-app.pid                                                 
    cd $FULL_PATH        
    #Use exec below if you want to launch it under myuser, 
    #don't forget to create /var/log/my-app.sys.log with appropriate permissions
    #exec sudo -u myuser sh -c "$NODE_PATH server.js >> /var/log/my-app.sys.log 2>&1" 
    exec $NODE_PATH server.js >> /var/log/my-app.sys.log 2>&1                     
end script                                                                        

pre-start script                                                                  
    echo "[`date`] (sys) Starting" >> /var/log/my-app.sys.log                     
end script                                                                        

pre-stop script                                                                   
    rm /var/run/my-app.pid                                                        
    echo "[`date`] (sys) Stopping" >> /var/log/my-app.sys.log                     
end script                                                                        

#uncomment respawn if you want to restart your service in case of crash
#respawn                                                                          
#respawn limit 50 30   

I do recommend to uncomment respawn after you will make sure that everything works ok.

UPDATE

I improved my script (please keep in mind that it works not under root but under regular user zn ):

#znapi.conf                                                                    
description "node.js zn api"                                        

env FULL_PATH="/home/zn/app.prod"                          
env NODE_PATH="/usr/bin/node"                                  
env LOG="/var/log/znapi.log"
env PIDFILE="/var/run/znapi.pid"

# Start up when the system hits any normal runlevel, and 
#start on filesystem or runlevel [2345]     
#start when mongod started
start on started mongod

# shuts down when the system goes to shutdown or reboot.
stop on runlevel [06]                                                              

respawn
respawn limit 50 5

pre-start script                                                    
    # check that log file exist or create it
    test -f $LOG || { touch $LOG; chown zn:zn $LOG; }

    # Date format same as (new Date()).toISOString() for consistency
    echo "[`date`] (sys) Starting" >> $LOG            
end script                                                          

script                                                                       
    export NODE_ENV=production
    exec start-stop-daemon --start -m -p $PIDFILE -c zn -d $FULL_PATH -x server.js >> $LOG 2>&1
end script                                                                   

pre-stop script                                                              
    rm $PIDFILE                                                   
    echo "[`date`] (sys) Stopping" >> $LOG                    
end script 
Nuno answered 2/7, 2014 at 11:45 Comment(2)
Thanks for this @Roman, I used it for my server. However, when running as a different user using exec sudo -u, environment variables exported above will not be set. I solved it by running `exec sudo -u myuser sh- c "PORT=3000 SOME_VAR=SOME_VALUE $NODE_PATH server.js [...]" but I'm wondering whether there's a way to get the env variables to automatically follow into the shell for myuser?Mistrot
@Mistrot Please try the improved version of my scriptNuno

© 2022 - 2024 — McMap. All rights reserved.