Skip to content

Instantly share code, notes, and snippets.

@leommoore
Last active March 23, 2019 11:29
Show Gist options
  • Save leommoore/5998406 to your computer and use it in GitHub Desktop.
Save leommoore/5998406 to your computer and use it in GitHub Desktop.
Linux - Running a Node Service (PM2)

#Linux - Running a Node Service (PM2) PM2 is a replacement for Forever which is used to run Node services (see http://devo.ps/blog/2013/06/26/goodbye-node-forever-hello-pm2.html). It has a number of advantages over forever:

  • Log aggregation
  • API
  • Terminal monitoring
  • Clustering
  • JSON configuration

Installation

npm install -g pm2

Usage/Features

$ npm install pm2 -g     # Install pm2 command line globally
$ pm2 start app.js -i 4  # Daemonize pm2 and Start 4 clustered instances of app.js
                         # You can also pass the 'max' params to start 
                         # the right numbers of processes depending of CPUs
$ pm2 list               # Display all processes status
$ pm2 monit              # Monitor all processes
$ pm2 logs               # Display all processes logs in streaming
$ pm2 dump               # Dump the states of all processes
$ pm2 stop pm2_id        # Stop specific process id
$ pm2 stopAll            # Stop all processes
$ pm2 resurrect          # Put online previously dumped processes
$ pm2 restart pm2_id     # Restart specific process
$ pm2 restartAll         # Restart all proccesses
$ pm2 stopAll            # Stop all processes
$ pm2 generate app       # Generate a JSON process configuration
$ pm2 web                # Health computer API endpoint (http://localhost:9615)

##Using the API If you want to monitor all the processes managed by PM2 as well as the status of the machine you can use the API to access the information using:

$ pm2 web     // This starts the api web interface

then point your browser to;

http://localhost:9615

and you get a nice JSON info such as:

{
  "system_info": {
    "hostname": "testsite.com",
    "uptime": 160304.333279073
  },
  "monit": {
    "loadavg": [0.671875, 0.3603515625, 0.263671875],
    "total_mem": 3155824640,
    "free_mem": 148484096,
    "cpu": [{
      "model": "Intel(R) Pentium(R) D CPU 3.20GHz",
      "speed": 3192,
      "times": {
        "user": 52938600,
        "nice": 400,
        "sys": 21269000,
        "idle": 1487940400,
        "irq": 0
      }
    }, {
      "model": "Intel(R) Pentium(R) D CPU 3.20GHz",
      "speed": 3192,
      "times": {
        "user": 45176300,
        "nice": 1000,
        "sys": 23592600,
        "idle": 1513845800,
        "irq": 100
      }
    }],
    "interfaces": {
      "lo": [{
        "address": "127.0.0.1",
        "family": "IPv4",
        "internal": true
      }, {
        "address": "::1",
        "family": "IPv6",
        "internal": true
      }],
      "eth0": [{
        "address": "192.168.1.30",
        "family": "IPv4",
        "internal": false
      }, {
        "address": "fe80::213:73ff:fe09:b340",
        "family": "IPv6",
        "internal": false
      }]
    }
  },
  "processes": [{
    "pid": 3106,
    "opts": {
      "script": "/usr/local/lib/node_modules/pm2/lib/HttpInterface.js",
      "name": "Pm2Http9615",
      "pm_exec_path": "/usr/local/lib/node_modules/pm2/lib/HttpInterface.js",
      "OLDPWD": "/var/www",
      "_": "/usr/local/bin/pm2",
      "COLORTERM": "gnome-terminal",
      "XAUTHORITY": "/home/leo/.Xauthority",
      "XDG_CURRENT_DESKTOP": "GNOME",
      "MDM_LANG": "en_IE.UTF-8",
      "XDG_RUNTIME_DIR": "/run/user/root",
      "DISPLAY": ":0.0",
      "WINDOWPATH": "7",
      "MDMSESSION": "default",
      "XDG_DATA_DIRS": "/usr/share/default:/usr/share/gnome:/usr/local/share/:/usr/share/:/usr/share/mdm/",
      "DBUS_SESSION_BUS_ADDRESS": "unix:abstract=/tmp/dbus-KRPisUnuie,guid=c9ab1a1c6dfa830b9070b86b51e14292",
      "LOGNAME": "root",
      "GNOME_DESKTOP_SESSION_ID": "this-is-deprecated",
      "LANGUAGE": "en_IE:en",
      "SHLVL": "2",
      "HOME": "/root",
      "MDM_XSERVER_LOCATION": "local",
      "MANDATORY_PATH": "/usr/share/gconf/default.mandatory.path",
      "GNOME_KEYRING_PID": "1877",
      "LANG": "en_IE.UTF-8",
      "PWD": "/var/www/api.nodenx.com",
      "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games",
      "DESKTOP_SESSION": "default",
      "MAIL": "/var/mail/root",
      "XDG_CONFIG_DIRS": "/etc/xdg/xdg-default:/etc/xdg",
      "SESSION_MANAGER": "local/nodenx.com:@/tmp/.ICE-unix/1953,unix/nodenx.com:/tmp/.ICE-unix/1953",
      "USERNAME": "leo",
      "DEFAULTS_PATH": "/usr/share/gconf/default.default.path",
      "SSH_AUTH_SOCK": "/run/user/leo/keyring-peNMFD/ssh",
      "USER": "root",
      "GNOME_KEYRING_CONTROL": "/run/user/leo/keyring-peNMFD",
      "WINDOWID": "44040197",
      "XDG_SESSION_COOKIE": "93d9e906acbca0047d713008516a80e1-1373717379.53815-388266902",
      "TERM": "xterm",
      "SHELL": "/bin/bash",
      "GPG_AGENT_INFO": "/run/user/leo/keyring-peNMFD/gpg:0:1",
      "SSH_AGENT_PID": "2036",
      "pm_out_log_path": "/root/.pm2/logs/Pm2Http9615-out.log",
      "fileOutput": "/root/.pm2/logs/Pm2Http9615-out.log",
      "pm_err_log_path": "/root/.pm2/logs/Pm2Http9615-err.log",
      "fileError": "/root/.pm2/logs/Pm2Http9615-err.log",
      "pm_pid_path": "/root/.pm2/pids/Pm2Http9615.pid",
      "pidFile": "/root/.pm2/pids/Pm2Http9615.pid",
      "pm_id": 2,
      "pm_uptime": 1373877151459,
      "restart_time": 0
    },
    "pm_id": 2,
    "status": "online",
    "monit": {
      "memory": 13643776,
      "cpu": 1.0679611650467329
    }
  }, {
    "pid": 21349,
    "opts": {
      "script": "server.js",
      "name": "server",
      "instances": 2,
      "pm_exec_path": "/var/www/testsite.com/server.js",
      "OLDPWD": "/var/www",
      "_": "/usr/local/bin/pm2",
      "COLORTERM": "gnome-terminal",
      "XAUTHORITY": "/home/leo/.Xauthority",
      "XDG_CURRENT_DESKTOP": "GNOME",
      "MDM_LANG": "en_IE.UTF-8",
      "XDG_RUNTIME_DIR": "/run/user/root",
      "DISPLAY": ":0.0",
      "WINDOWPATH": "7",
      "MDMSESSION": "default",
      "XDG_DATA_DIRS": "/usr/share/default:/usr/share/gnome:/usr/local/share/:/usr/share/:/usr/share/mdm/",
      "DBUS_SESSION_BUS_ADDRESS": "unix:abstract=/tmp/dbus-KRPisUnuie,guid=c9ab1a1c6dfa830b9070b86b51e14292",
      "LOGNAME": "root",
      "GNOME_DESKTOP_SESSION_ID": "this-is-deprecated",
      "LANGUAGE": "en_IE:en",
      "SHLVL": "2",
      "HOME": "/root",
      "MDM_XSERVER_LOCATION": "local",
      "MANDATORY_PATH": "/usr/share/gconf/default.mandatory.path",
      "GNOME_KEYRING_PID": "1877",
      "LANG": "en_IE.UTF-8",
      "PWD": "/var/www/api.nodenx.com",
      "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games",
      "DESKTOP_SESSION": "default",
      "MAIL": "/var/mail/root",
      "XDG_CONFIG_DIRS": "/etc/xdg/xdg-default:/etc/xdg",
      "SESSION_MANAGER": "local/nodenx.com:@/tmp/.ICE-unix/1953,unix/nodenx.com:/tmp/.ICE-unix/1953",
      "USERNAME": "leo",
      "DEFAULTS_PATH": "/usr/share/gconf/default.default.path",
      "SSH_AUTH_SOCK": "/run/user/leo/keyring-peNMFD/ssh",
      "USER": "root",
      "GNOME_KEYRING_CONTROL": "/run/user/leo/keyring-peNMFD",
      "WINDOWID": "44040197",
      "XDG_SESSION_COOKIE": "93d9e906acbca0047d713008516a80e1-1373717379.53815-388266902",
      "TERM": "xterm",
      "SHELL": "/bin/bash",
      "GPG_AGENT_INFO": "/run/user/leo/keyring-peNMFD/gpg:0:1",
      "SSH_AGENT_PID": "2036",
      "pm_out_log_path": "/root/.pm2/logs/server-out.log",
      "fileOutput": "/root/.pm2/logs/server-out.log",
      "pm_err_log_path": "/root/.pm2/logs/server-err.log",
      "fileError": "/root/.pm2/logs/server-err.log",
      "pm_pid_path": "/root/.pm2/pids/server.pid",
      "pidFile": "/root/.pm2/pids/server.pid",
      "pm_id": 0,
      "pm_uptime": 1373721692005,
      "restart_time": 0
    },
    "pm_id": 0,
    "status": "online",
    "monit": {
      "memory": 29233152,
      "cpu": 0
    }
  }]
}

##Service Startup Configuration You can set it to start as a service using:

$ sudo pm2 startup
 Adding system startup for /etc/init.d/pm2-init.sh ...
   /etc/rc0.d/K20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc1.d/K20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc6.d/K20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc2.d/S20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc3.d/S20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc4.d/S20pm2-init.sh -> ../init.d/pm2-init.sh
   /etc/rc5.d/S20pm2-init.sh -> ../init.d/pm2-init.sh

I added the NODE_ENV="production" to make sure it runs as a production application.

#!/bin/bash
#
#
# description: PM2 next gen process manager for Node.js
# processname: pm2
#
### BEGIN INIT INFO
# Provides:          pm2
# Required-Start:    pm2
# Required-Stop:     
# Should-Start:      
# Should-Stop:
# Default-Start:     
# Default-Stop:
# Short-Description: PM2 init script
# Description: PM2 is the next gen process manager for Node.js
### END INIT INFO

NAME=pm2
PM2=/usr/local/lib/node_modules/pm2/bin/pm2
NODE=/usr/local/bin/node
NPM2=$NODE $PM2

export HOME="/home/leo"
export NODE_ENV="production"
 
start() {
    echo "Starting $NAME"
    $NODE $PM2 stop
    $NODE $PM2 resurrect
}
 
stop() {
    $NODE $PM2 dump
    $NODE $PM2 stop
}
 
restart() {
    echo "Restarting $NAME"
    stop
    start
}
 
status() {
    echo "Status for $NAME:"
    $NODE $PM2 list
    RETVAL=$?
}
 
case "$1" in
    start)
        start
        ;;
    stop)
        stop
        ;;
    status)
        status
        ;;
    restart)
        restart
        ;;
    *)
        echo "Usage: {start|stop|status|restart}"
        exit 1
        ;;
esac
exit $RETVAL
@JuhQ
Copy link

JuhQ commented May 27, 2015

+1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment