PM2 is a process manager for Node apps with a built-in load balancer.
PM2 is perfect when you need to spread your stateless Node.js code accross all CPUs available on a server, to keep all processes alive forever and to 0s reload them.
- Built-in load balancer (using the native cluster module)
- Script daemonization
- 0s downtime reload for Node apps
- Generate SystemV/SystemD startup scripts (Ubuntu, Centos...)
- Pause unstable process (avoid infinite loop)
- Restart on file change with
--watch
- Monitoring in console
- Free server/pm2 monitoring by ping strategy
Tested with Node v0.11, v0.10 (https://travis-ci.org/Unitech/pm2).
The recommended Node.js version is v0.11.10
Compatible with CoffeeScript. Works on Linux & MacOS.
We're going to release a very nice product, a dashboard to monitor every part of your Node.js applications. Here are some links:
- Pitch + Survey People who fill the survey will be eligible for free license
- Newsletter Subscribe to be kept informed
Thanks in advance and we hope that you like PM2!
- Installation
- Usage
- Examples
- Differents ways to launch a process
- Options
- How to update PM2 ?
- Builtin remote monitoring
- Transitional state of apps
- Process listing
- Monitoring CPU/Memory usage
- Logs management
- Clustering
- Watch & Restart
- Reloading without downtime
- Make PM2 restart on server reboot
- JSON app declaration
- Specific features
- Configuration file
- Enabling Harmony ES6
- CoffeeScript
- Testing PM2 on your prod environment
- JSON app via pipe
- Stateless apps ?
- Transitional state of apps
- Setup PM2 on server: tutorial
- Logs and PID files
- Execute any script: What is fork mode ?
## Installation
The preferred Node version to run PM2, is the 0.11.10
The latest stable version is installable via NPM:
$ npm install pm2@latest -g
If the above fails:
$ npm install git://github.com/Unitech/pm2#master -g
Hello world:
$ pm2 start app.js
Raw examples:
$ pm2 start app.js --name my-api # Name process
$ pm2 start app.js -i max # Will start maximum processes with LB depending on available CPUs
# Listing
$ pm2 list # Display all processes status
$ pm2 jlist # Print process list in raw JSON
$ pm2 prettylist # Print process list in beautified JSON
$ pm2 describe 0 # Display all informations about a specific process
$ pm2 monit # Monitor all processes
# Builtin monitoring via PING strategy
$ pm2 subscribe [email protected] # Send an email if your server or pm2 is down
$ pm2 unsubscribe # Unable the remote monitoring
# Logs
$ pm2 logs # Display all processes logs in streaming
$ pm2 flush # Empty all log file
$ pm2 reloadLogs # Reload all logs
# Actions
$ pm2 stop all # Stop all processes
$ pm2 restart all # Restart all processes
$ pm2 reload all # Will 0s downtime reload (for NETWORKED apps)
$ pm2 gracefulReload all # Send exit message then reload (for networked apps)
$ pm2 stop 0 # Stop specific process id
$ pm2 restart 0 # Restart specific process id
$ pm2 delete 0 # Will remove process from pm2 list
$ pm2 delete all # Will remove all processes from pm2 list
# Misc
$ pm2 updatePM2 # Update in memory pm2
$ pm2 ping # Ensure pm2 dameon has been launched
$ pm2 sendSignal SIGUSR2 my-app # Send system signal to script
$ pm2 start app.js --no-daemon
$ pm2 start app.js -i max # Will start maximum processes depending on available CPUs
$ pm2 start app.js -i 3 # Will start 3 processes
$ pm2 start app.js -i max -- -a 23 # Pass arguments after -- to app.js
$ pm2 start app.js -x # Start app.js in fork mode instead of cluster
$ pm2 start app.js -x -- -a 23 # Start app.js in fork mode and pass arguments (-a 23)
$ pm2 start app.js --name serverone # Start a process an name it as server one
# you can now stop the process by doing
# pm2 stop serverone
$ pm2 start app.json # Start processes with options declared in app.json
# Go to chapter Multi process JSON declaration for more
$ pm2 start app.js -i max -e err.log -o out.log # Will start and generate a configuration file
$ pm2 start app.js --node-args="--debug=7001 --trace-deprecation" # --node-args command line option to pass options to node
$ pm2 --run-as-user foo start app.js # Start app.js as user foo instead of root (pm2 must be running as root)
$ pm2 --run-as-user foo --run-as-group bar start app.js # Start app.js as foo:bar instead of root:root (pm2 must be running as root)
For scripts in other languages:
$ pm2 start echo.coffee
$ pm2 start echo.php
$ pm2 start echo.py
$ pm2 start echo.sh
$ pm2 start echo.rb
$ pm2 start echo.pl
Options:
-h, --help output usage information
-V, --version output the version number
-v --verbose verbose level
-s --silent hide all messages
-m --mini-list display a compacted list without formatting
-f --force force actions
-n --name <name> set a <name> for script
-i --instances <number> launch [number] (load balanced) instances (for networked app)
-o --output <path> specify out log file
-e --error <path> specify error log file
-p --pid <pid> specify pid file
-x --execute-command execute a program using fork system
-u --user <username> define user when generating startup script
-c --cron <cron_pattern> restart a running process based on a cron pattern
-w --write write configuration in local folder
--interpreter <interpreter> the interpreter pm2 should use for executing app (bash, python...)
--no-daemon run pm2 daemon in the foreground if it doesn't exist already
--merge-logs merge logs
--watch watch application folder for changes
--node-args <node_args> space-delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"
--run-as-user <run_as_user> The user or uid to run a managed process as
--run-as-group <run_as_group> The group or gid to run a managed process as
Install the latest PM2 version :
$ npm install pm2@latest -g
Then update the in-memory PM2 :
$ pm2 updatePM2
On installation, you're asked if you want to enable the remote monitoring for your server or PM2. If accepted and if you set the right email, you will receive an email if something hangs (offline).
This monitoring strategy only do a ping at a regular interval to pm2.io servers.
If you want to enable it after installation just do :
$ pm2 subscribe [email protected]
# Once the monitoring enabled, you have to restart pm2 :
$ pm2 dump
$ pm2 kill
$ pm2 resurrect
If you want to stop the monitoring do :
$ pm2 unsubscribe
PM2 is a process manager, as said, PM2 can start, stop, restart and delete processes.
Start a process:
$ pm2 start app.js --name "my-api"
$ pm2 start web.js --name "web-interface"
Now let's say I need to stop the web-interface:
$ pm2 stop web-interface
As you can see the process hasn't disapeared. It is still there but now in stopped
status.
To restart it just do:
$ pm2 restart web-interface
Now I want to delete the app from the PM2 process list. To do that:
$ pm2 delete web-interface
To list all running processes:
$ pm2 list
# Or
$ pm2 [list|ls|l|status]
To get more details about a specific process:
$ pm2 describe 0
Monitor all processes launched:
$ pm2 monit
Displaying logs of specified process or all processes in realtime:
$ pm2 logs
$ pm2 logs big-api
$ pm2 flush # Clear all the logs
To reload all logs, you can send SIGUSR2
to the PM2 process.
You can also reload all logs via the command line with:
$ pm2 reloadLogs
--merge-logs : merge logs from different instances but keep error and out separated
Launch max
instances (max
depending on the number of CPUs available) and set the load balancer to balance queries among process:
$ pm2 start app.js --name "API" -i max
If your app is well-designed (stateless) you'll be able to process many more queries.
Important concepts to make a Node.js app stateless:
- Sessions must not be stored in memory but shared via a database (Redis, Mongo, whatever)
- WebSocket/Socket.io should communicate via a database
As opposed to restart
, which kills and restarts the process, reload
achieves a 0-second-downtime reload.
Warning This feature only works for apps in cluster mode (the default mode), that uses HTTP/HTTPS/Socket connections.
To reload an app:
$ pm2 reload api
If the reload system hasn't managed to reload gracefully, a timeout will simply kill the process and will restart it.
Sometimes you can experience a very long reload, or a reload that doesn't work (fallback to restart).
It means that your app still has open connections on exit.
To work around this problem you have to use the graceful reload.
Graceful reload is a mechanism that will send a shutdown message to your process before reloading it.
You can control the time that the app has to shutdown via the PM2_GRACEFUL_TIMEOUT
environment variable.
Example:
process.on('message', function(msg) {
if (msg == 'shutdown') {
// Your process is going to be reloaded
// You have to close all database/socket.io/* connections
console.log('Closing all connections...');
// You will have 4000ms to close all connections before
// the reload mechanism will try to do its job
setTimeout(function() {
console.log('Finished closing connections');
// This timeout means that all connections have been closed
// Now we can exit to let the reload mechanism do its job
process.exit(0);
}, 1500);
}
});
Then use the command:
$ pm2 gracefulReload [all|name]
When PM2 starts a new process to replace an old one, it will wait for the new process to begin listening to a connection before sending the shutdown message to the old one. If a script does not need to listen to a connection, it can manually tell PM2 that the process has started up by calling process.send('online')
.
PM2 has the amazing ability to generate startup scripts and configure them. PM2 is also smart enough to save all your process list and to bring back all your processes on restart.
$ pm2 startup [ubuntu|centos|systemd]
Warning It's tricky to make this feature work generically, so once PM2 has setup your startup script, reboot your server to make sure that PM2 has launched your apps!
Two types of startup scripts are available:
- SystemV init script (with the option
ubuntu
orcentos
) - SystemD init script (with the
systemd
option)
The startup options are using:
- ubuntu will use
updaterc.d
and the scriptlib/scripts/pm2-init.sh
- centos will use
chkconfig
and the scriptlib/scripts/pm2-init-centos.sh
- systemd will use
systemctl
and the scriptlib/scripts/pm2.service
Let's say you want the startup script to be executed under another user.
Just use the -u <username>
option !
$ pm2 startup ubuntu -u www
Dump all processes status and environment managed by pm2:
$ pm2 dump
It populates the file ~/.pm2/dump.pm2
by default.
To bring back the latest dump:
$ pm2 resurrect
pm2 can automatically restart your app when a file changes in the current directory or its subdirectories:
$ pm2 start app.js --watch
You can define parameters for your apps in processes.json
:
[{
"name" : "echo",
"script" : "examples/args.js",
"args" : "['--toto=heya coco', '-d', '1']",
"ignoreWatch" : ["[\\/\\\\]\\./", "node_modules"],
"watch" : "true",
"cwd" : "/this/is/a/path/to/start/script",
"env": {
"NODE_ENV": "production",
"AWESOME_SERVICE_API_TOKEN": "xxx"
}
}, {
"name" : "api",
"script" : "./examples/child.js",
"instances" : "4",
"error_file" : "./examples/child-err.log",
"out_file" : "./examples/child-out.log",
"pid_file" : "./examples/child.pid",
"exec_mode" : "cluster_mode",
"port" : 9005
}, {
"name" : "auto-kill",
"script" : "./examples/killfast.js",
"min_uptime" : "100",
"exec_mode" : "fork_mode",
}]
Then run:
$ pm2 start processes.json
$ pm2 stop processes.json
$ pm2 delete processes.json
$ pm2 restart processes.json
A few notes about JSON app declarations:
- All command line options passed when using the JSON app declaration will be dropped i.e.
$ cat node-app-1.json
{
"name" : "node-app-1",
"script" : "app.js",
"cwd" : "/srv/node-app-1/current"
}
$ pm2 --run-as-user app start node-app-1.json
$ ps aux | grep node-app
root 14735 5.8 1.1 752476 83932 ? Sl 00:08 0:00 pm2: node-app-1 <-- owned by the default user (root), not app
- JSON app declarations are additive. Continuing from above:
$ pm2 start node-app-2.json
$ ps aux | grep node-app
root 14735 5.8 1.1 752476 83932 ? Sl 00:08 0:00 pm2: node-app-1
root 24271 0.0 0.3 696428 24208 ? Sl 17:36 0:00 pm2: node-app-2
Note that if you execute pm2 start node-app-2
again, it will spawn an additional instance node-app-2.
-
cwd: your JSON declaration does not need to reside with your script. If you wished to maintain the JSON(s) in a location other than your script (say,
/etc/pm2/conf.d/node-app.json
) you will need to use the cwd feature. (Note, this is especially helpful for capistrano style directory structures that use symlinks.) Files can be either relative to the cwd directory, or absolute (example below.) -
The following are valid options for JSON app declarations:
[{
"name" : "node-app",
"cwd" : "/srv/node-app/current",
"script" : "bin/app.js",
"error_file" : "/var/log/node-app/node-app.stderr.log",
"out_file" : "log/node-app.stdout.log",
"pid_file" : "pids/node-geo-api.pid",
"run_as_user" : "app",
"run_as_group" : "www-data",
"instances" : "6",
"min_uptime" : "200",
"cron_restart" : "1 0 * * *",
"watch" : "false",
"merge_logs" : "true",
"exec_interpreter" : "node",
"one_launch_only" : "true",
"exec_mode" : "cluster_mode"
}]
Launching PM2 without daemonizing itself:
$ pm2 start app.js --no-daemon
Sending a system signal to a process:
$ pm2 sendSignal SIGUSR2 my-app
You can specifiy the following options by editing the file ~/.pm2/custom_options.sh
:
PM2_RPC_PORT
PM2_PUB_PORT
PM2_BIND_ADDR
PM2_API_PORT
PM2_GRACEFUL_TIMEOUT
PM2_MODIFY_REQUIRE
PM2_NODE_OPTIONS
$ pm2 web
You can enable Harmony ES6 by setting PM2_NODE_OPTIONS='--harmony'
environment variable option when you start PM2 (PM2 should not be already daemonized).
To pass this option by default, you can edit ~/.pm2/custom_options.sh
and add:
export PM2_NODE_OPTIONS='--harmony'
Then:
$ pm2 dump
$ pm2 exit
$ pm2 resurrect
If ES6 has been enabled you should see this message at the beggining of each PM2 command:
● ES6 mode
$ pm2 start my_app.js --node-args="--harmony"
$ pm2 start my_app.coffee
That's all!
## Statless appsWe recommend (and you must) write stateless NodeJS apps. Apps that don't retain any form of local variables or local instances or whatever local. Every data, states, websocket session, session data, must be shared via any kind of database.
We recommend using Redis for sharing session data, websocket.
- SocketIO with Redis : [https://github.com/LearnBoost/Socket.IO/wiki/Configuring-Socket.IO](Configuring SocketIO)
- Redis session store for Connect : https://github.com/visionmedia/connect-redis
We recommend following the 12 factor convention : http://12factor.net/
## Setup PM2 on a serverHow To Use PM2 to Setup a Node.js Production Environment On An Ubuntu VPS
## Log and PID filesBy default, logs (error and output), pid files, dumps, and PM2 logs are located in ~/.pm2/
:
.pm2/
├── dump.pm2
├── custom_options.sh
├── pm2.log
├── pm2.pid
├── logs
└── pids
The default mode of PM2 consists of wrapping the code of your node application into the Node Cluster module. It's called the cluster mode.
There is also a more classical way to execute your app, like node-forever does, called the fork mode.
In fork mode almost all options are the same as the cluster mode. But there is no reload
or gracefulReload
command.
By using the fork mode you will lose core features of PM2 like the automatic clusterization of your code over all CPUs available and the 0s reload.
So use it if you only need a forever-like behaviour.
Here is how to start your app within a fork:
$ pm2 start app.js -x # Will start your app.js in fork mode
$ pm2 list # You will see that on the row "mode" it's written "fork"
You can also exec scripts written in other languages:
$ pm2 start my-bash-script.sh -x --interpreter bash
$ pm2 start my-python-script.py -x --interpreter python
Pull-requests:
#!/bin/bash
read -d '' my_json <<_EOF_
[{
"name" : "app1",
"script" : "/home/projects/pm2_nodetest/app.js",
"instances" : "4",
"error_file" : "./logz/child-err.log",
"out_file" : "./logz/child-out.log",
"pid_file" : "./logz/child.pid",
"exec_mode" : "cluster_mode",
"port" : 4200
}]
_EOF_
echo $my_json | pm2 start -
Just try the tests before using PM2 on your production server
$ git clone https://github.com/Unitech/pm2.git
$ cd pm2
$ npm install # Or do NODE_ENV=development npm install if some packages are missing
$ npm test
If a test is broken please report us issues here Also make sure you have all dependencies needed. For Ubuntu:
$ sudo apt-get install build-essential
# nvm is a Node.js version manager - https://github.com/creationix/nvm
$ wget -qO- https://raw.github.com/creationix/nvm/master/install.sh | sh
$ nvm install v0.11.10
$ nvm use v0.11.10
$ nvm alias default v0.11.10
To hack PM2, it's pretty simple:
$ pm2 kill # kill the current pm2
$ git clone my_pm2_fork.git
$ cd pm2/
$ DEBUG=* PM2_DEBUG=true ./bin/pm2 --no-daemon
Each time you edit the code, be sure to kill and restart pm2 to make changes taking effect.
$ npm install git://github.com/Unitech/pm2#development -g
First, install the lastest pm2 version:
$ npm install -g pm2@latest
So if you feel that this problem is important for your use case, use the fork mode instead. By using the fork mode you will lose core features of PM2 like the automatic clusterization of your code over all CPUs available and the 0s reload.
$ pm2 start index.js -x # start my app in fork mode
For more information about this, see issue #74.
When using the cluster mode (by default) you can't use ports from 0 to 1024. If you really need to exec in this range use the fork mode with the -x
parameter.
By using the fork mode you will lose core features of PM2 like the automatic clusterization of your code over all CPUs available and the 0s reload.
- Goodbye node-forever, hello PM2
- http://www.allaboutghost.com/keep-ghost-running-with-pm2/
- http://blog.ponyfoo.com/2013/09/19/deploying-node-apps-to-aws-using-grunt
- http://www.allaboutghost.com/keep-ghost-running-with-pm2/
- http://bioselemental.com/keeping-ghost-alive-with-pm2/
- http://blog.chyld.net/installing-ghost-on-ubuntu-13-10-aws-ec2-instance-with-pm2/
- http://blog.marvinroger.fr/gerer-ses-applications-node-en-production-pm2/
- https://www.codersgrid.com/2013/06/29/pm2-process-manager-for-node-js/
- http://www.z-car.com/blog/programming/how-to-rotate-logs-using-pm2-process-manager-for-node-js
- http://yosoftware.com/blog/7-tips-for-a-node-js/
- https://www.exponential.io/blog/nodeday-2014-moving-a-large-developer-workforce-to-nodejs
- http://blog.rapsli.ch/posts/2013/2013-10-17-node-monitor-pm2.html
- https://coderwall.com/p/igdqyw
- http://revdancatt.com/2013/09/17/node-day-1-getting-the-server-installing-node-and-pm2/
- https://medium.com/tech-talk/e7c0b0e5ce3c
195 tknew2
184 Alexandre Strzelewicz
20 Alex Kocharin
8 soyuka
6 sailxjx
5 Bret Copeland
4 AS
4 Ville Walveranta
4 achingbrain
3 Ben Postlethwaite
3 Evan You
2 Frederico Silva
2 Ivan Seidel
2 MATSUU Takuto
2 Oleg
2 Willian
2 Yani Iliev
1 Almog Melamed
1 Brent Burgoyne
1 Daniel Pihlstrom
1 Ed Hubbell
1 Eugene Lucash
1 Gil Pedersen
1 Hao-kang Den
1 John Hurliman
1 Jose V. Trigueros
1 Josh Skidmore
1 Juozas Valenčius
1 Kevin Gao
1 Loïc Mahieu
1 Mark Evans
1 Nathan Peck
1 TruongSinh Tran-Nguyen
1 Wes Mason
1 Zihua Li
1 perfectworks
1 subeeshcbabu
Thanks to Devo.ps and Wiredcraft for their knowledge and expertise.
# LicenseFiles in lib/
are made available under the terms of the GNU Affero General Public License (AGPL).
pm2-interface
is made under the terms of the Apache V2 license.