#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
npm install -g pm2
$ 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
+1