- Installation
- Folder structure
- Usage
- Examples
- Different ways to launch a process
- Options
- How to update PM2?
- PM2 tab-completion
- Allow PM2 to bind apps on port 80/443 without root
- Transitional state of apps
- Process listing
- Automatic restart process based on memory
- Monitoring CPU/Memory usage
- Logs management
- Clustering
- Multiple PM2 on the same server
- Watch & Restart
- Reloading without downtime
- Make PM2 restart on server reboot
- JS/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 latest PM2 stable version is installable via NPM:
$ npm install pm2@latest -g
If the above fails use:
$ npm install git://github.com/Unitech/pm2#master -g
Once PM2 is started, it automatically create these folders:
$HOME/.pm2
will contain all PM2 related files$HOME/.pm2/logs
will contain all applications logs$HOME/.pm2/pids
will contain all applications pids$HOME/.pm2/pm2.log
PM2 logs$HOME/.pm2/pm2.pid
PM2 pid$HOME/.pm2/rpc.sock
Socket file for remote commands$HOME/.pm2/pub.sock
Socket file for publishable events$HOME/.pm2/conf.js
PM2 Configuration
Hello world:
$ pm2 start app.js
# Fork mode
$ pm2 start app.js --name my-api # Name process
# Cluster mode
$ pm2 start app.js -i 0 # Will start maximum processes with LB depending on available CPUs
$ pm2 start app.js -i max # Same as above, but deprecated yet.
# 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
# Logs
$ pm2 logs [--raw] # 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 reset <process> # Reset meta data (restarted time...)
$ pm2 updatePM2 # Update in memory pm2
$ pm2 ping # Ensure pm2 daemon has been launched
$ pm2 sendSignal SIGUSR2 my-app # Send system signal to script
$ pm2 start app.js --no-daemon
$ pm2 start app.js --no-vizion
$ pm2 start app.js --no-autorestart
$ pm2 start app.js # Start app.js
$ pm2 start app.js -- -a 23 # Pass arguments '-a 23' argument to app.js script
$ 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.js --node-args="--debug=7001" # --node-args to pass options to node V8
$ pm2 start app.js -i 0 # Start maximum processes depending on available CPUs (cluster mode)
$ pm2 start app.js --log-date-format "YYYY-MM-DD HH:mm Z" # Log will be prefixed with custom time format
$ 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 -e err.log -o out.log # Start and specify error and out log
For scripts in other languages:
$ pm2 start echo.pl --interpreter=perl
$ pm2 start echo.coffee
$ pm2 start echo.php
$ pm2 start echo.py
$ pm2 start echo.sh
$ pm2 start echo.rb
The interpreter is set by default with this equivalence:
{
".sh": "bash",
".py": "python",
".rb": "ruby",
".coffee" : "coffee",
".php": "php",
".pl" : "perl",
".js" : "node"
}
Options:
-h, --help output usage information
-V, --version output the version number
-v --version get version
-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] instances (for networked app)(load balanced)
-l --log [path] specify entire log file (error and out are both included)
-o --output <path> specify out log file
-e --error <path> specify error log file
-p --pid <pid> specify pid file
--max-memory-restart <memory> specify max memory amount used to autorestart (in megaoctets)
--env <environment_name> specify environment to get specific env variables (for JSON declaration)
-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...)
--log-date-format <momentjs format> add custom prefix timestamp to logs
--no-daemon run pm2 daemon in the foreground if it doesn't exist already
--merge-logs merge logs from different instances but keep error and out separated
--watch watch application folder for changes
--ignore-watch <folders|files> folder/files to be ignored watching, chould be a specific name or regex - e.g. --ignore-watch="test node_modules "some scripts""
--node-args <node_args> space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"
--no-color skip colors
--no-vizion skip vizion features (versioning control)
--no-autorestart do not automatically restart apps
Install the latest pm2 version :
$ npm install pm2@latest -g
Then update the in-memory PM2 :
$ pm2 update
Tab-completion for pm2.
Append pm2 completion script to your .bashrc or .zshrc file:
$ pm2 completion install
Or manually append completion script to your ~/.bashrc or ~/.zshrc file:
$ pm2 completion >> ~/.bashrc # or ~/.zshrc
Then source your .bashrc or .zshrc file for current session:
$ source ~/.bashrc # or ~/.zshrc
You can add pm2 completion to your current session this way:
$ . <(pm2 completion)
It’s a general rule that you shouldn’t run node as root, but only root can bind to ports less than 1024. This is where authbind comes in. Authbind allows non-root users to bind to ports less than 1024.
$ sudo apt-get install authbind
$ sudo touch /etc/authbind/byport/80
$ sudo chown user /etc/authbind/byport/80
$ sudo chmod 755 /etc/authbind/byport/80
$ authbind --deep pm2 update
Now you can start applications with PM2 that can bind to port 80 without being root!
It's recommended to put an alias in your .bashrc file:
alias pm2='authbind --deep pm2'
PM2 is a process manager. It manages your applications states, so you 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 disappeared. It's still there but 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 so:
$ 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 show 0
PM2 gives you a simple way to monitor the resource usage of your application. You can monitor memory and cpu very easily, straight from your terminal:
$ pm2 monit
Please note that Keymetrics allows to monitor applications much better, from errors, performances, vital signs and much more.
## Clustering (cluster_mode)The cluster mode allows to scale your Node.js application accross all CPUs available and to update them without any downtime!
It's perfectly fitted for networked applications handling HTTP(s)/UDP/TCP connections.
To enable the cluster mode, just pass the -i option:
$ pm2 start app.js -i 1
You can pass multiple values to the instances (-i) option:
# Start the maximum processes depending on available CPUs
$ pm2 start app.js -i 0
# Start the maximum processes -1 depending on available CPUs
$ pm2 start app.js -i -1
# Start 3 processes
$ pm2 start app.js -i 3
- You don't need to modify anything from your code to be able to use this nifty feature.
- In your application the environment variable
NODE_APP_INSTANCE
is exposed so you can listen for different port if needed. (e.g .listen(8000 + process.env.NODE_APP_INSTANCE)) - Be sure your application is stateless meaning that there is not any local data stored in the process, like sessions/websocket connections etc. Use Redis, Mongo or other DB to share states between processes
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, that uses HTTP/HTTPS/Socket connections.
To reload an app:
$ pm2 reload api
If the reload system hasn't managed to reload your app, a timeout will fallback to a classic restart.
Sometimes you can experience a very long reload, or a reload that doesn't work (fallback to restart) meaning that your app still has open connections on exit. Or you may need to close all databases connections, clear a data queue or whatever.
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 or a timeout before sending the shutdown message to the old one. You can define the timeout value with the PM2_GRACEFUL_LISTEN_TIMEOUT
environament variable. 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 allows you to manage logs easily. You can display all application logs in real-time, flush them, and reload them. There are also different ways to configure how PM2 will handle your logs (separated in different files, merged, with timestamp...) without modifying anything in your code.
Displaying logs of a specified process or of all processes in real-time:
$ pm2 logs
$ pm2 logs big-api
$ pm2 flush # Clear all the logs
You can configure a Cron Job to call this command every X days. Or you can install Log rotate to handle the log rotation.
Reloading logs is specially usefull for Logrotate or any other rotating log system.
You can reload logs by sending SIGUSR2
to the PM2 process.
You can also reload all logs via the command line with:
$ pm2 reloadLogs
$ pm2 start echo.js --merge-logs --log-date-format="YYYY-MM-DD HH:mm Z"
Options:
--merge-logs do not postfix log file with process id
--log-date-format <format> prefix logs with formated timestamp
-l --log [path] specify entire log file (error and out are both included)
-o --output <path> specify out log file
-e --error <path> specify error log file
{
"script" : "echo.js",
"error_file" : "err.log",
"out_file" : "out.log",
"merge_logs" : true,
"log_date_format" : "YYYY-MM-DD HH:mm Z"
}
Note: To merge all logs into the same file set the same value for error_file
, out_file
.
PM2 allows to restart an application based on a memory limit.
$ pm2 start big-array.js --max-memory-restart 20M
{
"name" : "max_mem",
"script" : "big-array.js",
"max_memory_restart" : "20M"
}
pm2.start({
name : "max_mem",
script : "big-array.js",
max_memory_restart : "20M"
}, function(err, proc) {
// Processing
});
Units can be K(ilobyte), M(egabyte), G(igabyte).
50M
50K
1G
PM2 can generate startup scripts and configure them. PM2 is also smart enough to save all your process list and to bring back all your processes at machine restart.
$ pm2 startup
# auto-detect platform
$ pm2 startup [platform]
# render startup-script for a specific platform, the [platform] could be one of:
# ubuntu|centos|redhat|gentoo|systemd|darwin|amazon
Once you have started the apps and want to keep them on server reboot do:
$ pm2 save
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!
Three types of startup scripts are available:
- SystemV init script (with the option
ubuntu
orcentos
) - OpenRC init script (with the option
gentoo
) - 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/redhat will use
chkconfig
and the scriptlib/scripts/pm2-init-centos.sh
- gentoo will use
rc-update
and the scriptlib/scripts/pm2
- systemd will use
systemctl
and the scriptlib/scripts/pm2.service
- darwin will use
launchd
to load a specificplist
to resurrect processes after reboot.
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|save]
It populates the file ~/.pm2/dump.pm2
by default.
To bring back the latest dump:
$ pm2 resurrect
The client and daemon communicates via socket files available in $HOME/.pm2/[pub.sock|rpc.sock]
You can start multiple PM2 instances by changing the PM2_HOME
environmnent variable.
$ PM2_HOME='.pm2' pm2 start echo.js --name="echo-node-1"
$ PM2_HOME='.pm3' pm2 start echo.js --name="echo-node-2"
This will start two different PM2 instances. To list processes managed by each different instances do:
$ PM2_HOME='.pm2' pm2 list
$ PM2_HOME='.pm3' pm2 list
PM2 can automatically restart your app when a file changes in the current directory or its subdirectories:
$ pm2 start app.js --watch
If --watch
is enabled, stopping it won't stop watching:
pm2 stop 0
will not stop watchingpm2 stop --watch 0
will stop watching
Restart toggle the watch
parameter when triggered.
To watch specific paths, please use a JS/JSON app declaration, watch
can take a string or an array of paths. Default is true
:
{
"watch": ["server", "client"],
"ignore_watch" : ["node_modules", "client/img"],
"watch_options": {
"followSymlinks": false
}
}
As specified in the Schema:
watch
can be a boolean, an array of paths or a string representing a path. Default tofalse
ignore_watch
can be an array of paths or a string, it'll be interpreted by chokidar as a glob or a regular expression.watch_options
is an object that will replace options given to chokidar. Please refer to chokidar documentation for the definition.
PM2 is giving chokidar these Default options:
var watch_options = {
persistent : true,
ignoreInitial : true
}
When working with NFS devices you'll need to set usePolling: true
as stated in this chokidar issue.
PM2 empowers your process management workflow, by allowing you to fine-tune the behavior, options, environment variables, logs files... of each process you need to manage via JSON/JSON5/JS configuration.
It's particularly usefull for micro service based applications.
You can define parameters for your apps in a JS/JSON file:
{
"apps" : [{
"name" : "worker-app",
"script" : "worker.js",
"args" : ["--toto=heya coco", "-d", "1"],
"watch" : true,
"node_args" : "--harmony",
"merge_logs" : true,
"cwd" : "/this/is/a/path/to/start/script",
"env": {
"NODE_ENV": "production",
"AWESOME_SERVICE_API_TOKEN": "xxx"
}
},{
"name" : "api-app",
"script" : "api.js",
"instances" : 4,
"exec_mode" : "cluster_mode",
"error_file" : "./examples/child-err.log",
"out_file" : "./examples/child-out.log",
"pid_file" : "./examples/child.pid"
}]
}
Then you can run:
# Start all apps
$ pm2 start processes.js[on]
# Stop
$ pm2 stop processes.js[on]
# Restart
$ pm2 start processes.js[on]
## Or
$ pm2 restart processes.js[on]
# Reload
$ pm2 reload processes.js[on]
# Graceful Reload
$ pm2 gracefulReload processes.js[on]
# Delete from PM2
$ pm2 delete processes.js[on]
The following are valid options for JSON app declarations:
{
"name" : "node-app",
"cwd" : "/srv/node-app/current",
"args" : ["--toto=heya coco", "-d", "1"],
"script" : "bin/app.js",
"node_args" : ["--harmony", " --max-stack-size=102400000"],
"log_date_format" : "YYYY-MM-DD HH:mm Z",
"error_file" : "/var/log/node-app/node-app.stderr.log",
"out_file" : "log/node-app.stdout.log",
"pid_file" : "pids/node-geo-api.pid",
"instances" : 6, //or 0 => 'max'
"min_uptime" : "200s", // 200 seconds, defaults to 1000
"max_restarts" : 10, // defaults to 15
"max_memory_restart": "1M", // 1 megabytes, e.g.: "2G", "10M", "100K", 1024 the default unit is byte.
"cron_restart" : "1 0 * * *",
"watch" : false,
"ignore_watch" : ["[\\/\\\\]\\./", "node_modules"],
"merge_logs" : true,
"exec_interpreter" : "node",
"exec_mode" : "fork",
"autorestart" : false, // enable/disable automatic restart when an app crashes or exits
"vizion" : false, // enable/disable vizion features (versioning control)
"env": {
"NODE_ENV": "production",
"AWESOME_SERVICE_API_TOKEN": "xxx"
}
}
Field | Type | Example | Description |
---|---|---|---|
name | string | "myAPI" | name your app will have in PM2 |
script | string | "bin/app.js" | path of your app |
args | list | ["--enable-logs", "-n", "15"] | arguments given to your app when it is launched |
node_args | list | ["--harmony", "--max-stack-size=1024"] | arguments given to node when it is launched |
cwd | string | "/var/www/app/prod" | the directory from which your app will be launched |
exec_mode | string | "cluster" | "fork" mode is used by default, "cluster" mode can be configured with instances field |
instances | number | 4 | number of instances for your clustered app, 0 means as much instances as you have CPU cores. a negative value means CPU cores - value (e.g -1 on a 4 cores machine will spawn 3 instances) |
exec_interpreter | string | "node" | defaults to "node". can be "python", "ruby", "bash" or whatever interpreter you wish to use. "none" will execute your app as a binary executable |
log_date_format | string | "YYYY-MM-DD HH:mm Z" | format in which timestamps will be displayed in the logs |
error_file | string | "/var/log/node-app/node-app.stderr.log" | path to the specified error log file. PM2 generates one by default if not specified and you can find it by typing pm2 desc <app id> |
out_file | string | "/var/log/node-app/node-app.stdout.log" | path to the specified output log file. PM2 generates one by default if not specified and you can find it by typing pm2 desc <app id> |
pid_file | string | "pids/node-geo-api.pid" | path to the specified pid file. PM2 generates one by default if not specified and you can find it by typing pm2 desc <app id> |
merge_logs | boolean | false | defaults to false. if true, it will merge logs from all instances of the same app into the same file |
cron_restart | string | "1 0 * * *" | a cron pattern to restart your app. only works in "cluster" mode for now. soon to be avaible in "fork" mode as well |
watch | boolean | true | enables the watch feature, defaults to "false". if true, it will restart your app everytime a file change is detected on the folder or subfolder of your app. |
ignore_watch | list | ["[\/\\]\./", "node_modules"] | list of regex to ignore some file or folder names by the watch feature |
max_restarts | number | 10 | number of consecutive unstable restarts (less than 1sec interval) before your app is considered errored and stop being restarted by PM2. defaults to 15. |
max_memory_restart | string | "150M" | your app will be restarted by PM2 if it exceeds the amount of memory specified. human-friendly format : it can be "10M", "100K", "2G" and so on... |
env | object | {"NODE_ENV": "production", "ID": "42"} | env variables which will appear in your app |
autorestart | boolean | false | true by default. if false, PM2 will not restart your app if it crashes or ends peacefully |
vizion | boolean | false | true by default. if false, PM2 will start without vizion features (versioning control metadatas) |
post_update | list | ["npm install", "echo launching the app"] | a list of commands which will be executed after you perform a Pull/Upgrade operation from Keymetrics dashboard |
force | boolean | true | defaults to false. if true, you can start the same script several times which is usually not allowed by PM2 |
next_gen_js | boolean | true | defaults to false. if true, PM2 will launch your app using embedded BabelJS features which means you can run ES6/ES7 javascript code |
The completely definitions:
{
"script": {
"type": "string",
"require": true
},
"args": {
"type": [
"array",
"string"
]
},
"node_args": {
"type": [
"array",
"string"
]
},
"name": {
"type": "string"
},
"max_memory_restart": {
"type": [
"string",
"number"
],
"regex": "^\\d+(G|M|K)?$",
"ext_type": "sbyte",
"desc": "it should be a NUMBER - byte, \"[NUMBER]G\"(Gigabyte), \"[NUMBER]M\"(Megabyte) or \"[NUMBER]K\"(Kilobyte)"
},
"instances": {
"type": "number",
"min": 0
},
"log_file": {
"type": [
"boolean",
"string"
],
"alias": "log"
},
"error_file": {
"type": "string",
"alias": "error"
},
"out_file": {
"type": "string",
"alias": "output"
},
"pid_file": {
"type": "string",
"alias": "pid"
},
"cron_restart": {
"type": "string",
"alias": "cron"
},
"cwd": {
"type": "string"
},
"merge_logs": {
"type": "boolean"
},
"watch": {
"type": "boolean"
},
"ignore_watch": {
"type": [
"array",
"string"
]
},
"watch_options": {
"type": "object"
},
"env": {
"type": ["object", "string"]
},
"^env_\\S*$": {
"type": [
"object",
"string"
]
},
"log_date_format": {
"type": "string"
},
"min_uptime": {
"type": [
"number",
"string"
],
"regex": "^\\d+(h|m|s)?$",
"desc": "it should be a NUMBER - milliseconds, \"[NUMBER]h\"(hours), \"[NUMBER]m\"(minutes) or \"[NUMBER]s\"(seconds)",
"min": 100,
"ext_type": "stime"
},
"max_restarts": {
"type": "number",
"min": 0
},
"exec_mode": {
"type": "string",
"regex": "^(cluster|fork)(_mode)?$",
"alias": "executeCommand",
"desc": "it should be \"cluster\"(\"cluster_mode\") or \"fork\"(\"fork_mode\") only"
},
"exec_interpreter": {
"type": "string",
"alias": "interpreter"
},
"write": {
"type": "boolean"
},
"force": {
"type": "boolean"
}
}
- 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"
}
- You can start as many JSON app declarations as you want. 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 wish 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 thecwd
feature (Note, this can be really helpful for capistrano style directory structures that uses symlinks). Files can be either relative to thecwd
directory, or absolute (see example below). -
All the keys can be used in a JSON configured file, but will remain almost the same on the command line e.g.:
exec_interpreter -> --interpreter
exec_mode -> --execute_command
max_restarts -> --max_restarts
force -> --force
If the alias
exists, you can use it as a CLI option, but do not forget to turn the camelCasing to underscore split executeCommand
to --execute_command
.
Notes
-
Using quotes to make an ESC, e.g.:
$pm2 start test.js --node-args "port=3001 sitename='first pm2 app'"
The
nodeArgs
argument will be parsed as[ "port=3001", "sitename=first pm2 app" ]
but not
[ "port=3001", "sitename='first", "pm2", "app'" ]
-
RegExp key
Matches the keys of configured JSON by RegExp (not by string comparison), e.g.
^env_\\S*$
will match allenv
keys likeenv_production
,env_test
, and valid them according to the schemas specifications. -
Special
ext_type
-
min_uptime
Value of
min_uptime
can be:- Number
e.g.
"min_uptime": 3000
means 3000 milliseconds. - String
Therefore, we are making it short and easy to configure:
h
,m
ands
, e.g.:"min_uptime": "1h"
means one hour,"min_uptime": "5m"
means five minutes and"min_uptime": "10s"
means ten seconds (those will be transformed into milliseconds).
- Number
e.g.
-
max_memory_restart
Value of
max_memory_restart
can be:- Number
e.g.
"max_memory_restart": 1024
means 1024 bytes (NOT BITS). - String
Therefore, we are making it short and easy to configure:
G
,M
andK
, e.g.:"max_memory_restart": "1G"
means one gigabytes,"max_memory_restart": "5M"
means five megabytes and"max_memory_restart": "10K"
means ten kilobytes (those will be transformed into byte(s)).
- Number
e.g.
-
-
Optional values
For example
exec_mode
can takecluster
(cluster_mode
) orfork
(fork_mode
) as possible values. -
Things to know
-
maximum
"instances": 0
means that we will launch the maximum processes possible according to the numbers of CPUs (cluster mode) -
array
args
,node_args
andignore_watch
could be type ofArray
(e.g.:"args": ["--toto=heya coco", "-d", "1"]
) orstring
(e.g.:"args": "--to='heya coco' -d 1"
)
-
Make sure you have tail.exe in your path, confirm using "where"
C:\>where tail
C:\Program Files (x86)\Git\bin\tail.exe
Tail can be found as part of Git, Cygwin and MingW packages. Tail needs to be able to support "-f" and "-n" options.
# DeploymentPM2 embed a simple and powerful deployment system with revision tracing. It's based on https://github.com/visionmedia/deploy
A step-by-step tutorial is available here : Deploy and Iterate faster with PM2 deploy
Please read the Considerations to use PM2 deploy
1- Generate a sample ecosystem.json file that list processes and deployment environment
$ pm2 ecosystem
In the current folder a ecosystem.json
file will be created.
It contains this:
{
"apps" : [{
"name" : "API",
"script" : "app.js",
"env": {
"COMMON_VARIABLE": "true"
},
"env_production" : {
"NODE_ENV": "production"
}
},{
"name" : "WEB",
"script" : "web.js"
}],
"deploy" : {
"production" : {
"user" : "node",
"host" : "212.83.163.1",
"ref" : "origin/master",
"repo" : "[email protected]:repo.git",
"path" : "/var/www/production",
"post-deploy" : "pm2 startOrRestart ecosystem.json --env production"
},
"dev" : {
"user" : "node",
"host" : "212.83.163.1",
"ref" : "origin/master",
"repo" : "[email protected]:repo.git",
"path" : "/var/www/development",
"post-deploy" : "pm2 startOrRestart ecosystem.json --env dev",
"env" : {
"NODE_ENV": "dev"
}
}
}
}
Edit the file according to your needs.
2- Be sure that you have the public ssh key on your local machine
$ ssh-keygen -t rsa
$ ssh-copy-id [email protected]
3- Now initialize the remote folder with:
$ pm2 deploy <configuration_file> <environment> setup
E.g:
$ pm2 deploy ecosystem.json production setup
This command will create all the folders on your remote server.
4- Deploy your code
$ pm2 deploy ecosystem.json production
Now your code will be populated, installed and started with PM2
## Deployment optionsDisplay deploy help via pm2 deploy help
:
$ pm2 deploy <configuration_file> <environment> <command>
Commands:
setup run remote setup commands
update update deploy to the latest release
revert [n] revert to [n]th last deployment or 1
curr[ent] output current release commit
prev[ious] output previous release commit
exec|run <cmd> execute the given <cmd>
list list previous deploy commits
[ref] deploy to [ref], the "ref" setting, or latest tag
$ pm2 startOrRestart all.json # Invoke restart on all apps in JSON
$ pm2 startOrReload all.json # Invoke reload
$ pm2 startOrGracefulReload all.json # Invoke gracefulReload
Just add the "key" attribute with file path to the .pem key within the attributes "user", "hosts"...
"production" : {
"key" : "/path/to/some.pem",
"user" : "node",
"host" : "212.83.163.1",
"ref" : "origin/master",
"repo" : "[email protected]:repo.git",
"path" : "/var/www/production",
"post-deploy" : "pm2 startOrRestart ecosystem.json --env production"
},
- You might want to commit your node_modules folder (#622) or add the
npm install
command to thepost-deploy
section:"post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
- Verify that your remote server has the permission to git clone the repository
- You can declare specific environment variable depending on the environment you want to deploy the code to. For instance to declare variables for the production environment, just add "env_production": {} and declare that variables.
- PM2 will look by default to
ecosystem.json
. So you can skip the <configuration_file> options if it's the case - You can embed the "apps" & "deploy" section in the package.json
- It deploys your code via ssh, you don't need any dependencies
- Process are initialized / started automatically depending on application name in
ecosystem.json
- PM2-deploy repository is there: pm2-deploy
The module is https://github.com/Unitech/pm2-deploy Feel free to PR for any changes or fix.
# Using PM2 programmaticallyPM2 can be used programmatically, meaning that you can embed a process manager directly in your code, spawn processes, keep them alive even if the main script is exited.
Check out this article for more informations.
This will require pm2, launch test.js
, list processes then exit the script.
You will notice that after exiting this script you will be able to see test.js
process with pm2 list
$ npm install pm2 --save
var pm2 = require('pm2');
// Connect or launch PM2
pm2.connect(function(err) {
// Start a script on the current folder
pm2.start('test.js', { name: 'test' }, function(err, proc) {
if (err) throw new Error('err');
// Get all processes running
pm2.list(function(err, process_list) {
console.log(process_list);
// Disconnect to PM2
pm2.disconnect(function() { process.exit(0) });
});
});
})
Method name | API |
---|---|
Connect/Launch | pm2.connect(fn(err){}) |
Disconnect | pm2.disconnect(fn(err, proc){}) |
Consideration with .connect: the .connect method connect to the local PM2, but if PM2 is not up, it will launch it and will put in in background as you launched it via CLI.
<tr>
<td><b>Reload</b></td>
<td>pm2.reload(proc_name|all, fn(err, proc){})</td>
</tr>
<tr>
<td><b>Graceful Reload</b></td>
<td>pm2.gracefulReload(proc_name|all, fn(err, proc){})</td>
</tr>
Method name | API |
---|---|
Start | pm2.start(script_path|json_object|json_path, options, fn(err, proc){}) |
Options | nodeArgs(arr), scriptArgs(arr), name(str), instances(int), error(str), output(str), pid(str), cron(str), mergeLogs(bool), watch(bool), runAsUser(int), runAsGroup(int), executeCommand(bool), interpreter(str), write(bool) |
Restart | pm2.restart(proc_name|proc_id|all, fn(err, proc){}) |
Stop | pm2.stop(proc_name|proc_id|all, fn(err, proc){}) |
Delete | pm2.delete(proc_name|proc_id|all, fn(err, proc){}) |
Method name | API |
---|---|
List | pm2.list(fn(err, list){}) |
Describe process | pm2.describe(proc_name|proc_id, fn(err, list){}) |
Dump (save) | pm2.dump(fn(err, ret){}) |
Flush logs | pm2.flush(fn(err, ret){}) |
Reload logs | pm2.reloadLogs(fn(err, ret){}) |
Send signal | pm2.sendSignalToProcessName(signal,proc,fn(err, ret){}) |
Generate start script | pm2.startup(platform, fn(err, ret){}) |
Kill PM2 | pm2.killDaemon(fn(err, ret){}) |
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 specify 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_KILL_TIMEOUT
$ pm2 web
The --node-args
option permit to launch script with V8 flags, so to enable harmony for a process just do this:
$ pm2 start my_app.js --node-args="--harmony"
And with JSON declaration:
[{
"name" : "ES6",
"script" : "es6.js",
"node_args" : "--harmony"
}]
$ pm2 start server.coffee --interpreter coffee
That's all!
## Stateless 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.
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
In fork mode almost all options are the same as the cluster mode. But there is no reload
or gracefulReload
command.
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
The interpreter is deduced from the file extension from the following list.
To run a non-JS interpreter you must set exec_mode
to fork_mode
and exec_interpreter
to your interpreter of choice.
For example:
{
"apps" : [{
"name" : "bash-worker",
"script" : "./a-bash-script",
"exec_interpreter": "bash",
"exec_mode" : "fork_mode"
}, {
"name" : "ruby-worker",
"script" : "./some-ruby-script",
"exec_interpreter": "ruby",
"exec_mode" : "fork_mode"
}]
}
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.14
$ nvm use v0.11.14
$ nvm alias default v0.11.14
To hack PM2, it's very 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
Don't use the cluster_mode via -i option.
- Vagrant and pm2 #289
- Start the same app on different ports #322
- Using ansible with pm2
- Cron string as argument
- Restart when process reaches a specific memory amount
- Sticky sessions and socket.io discussion
- EACCESS - understanding pm2 user/root rights
- Goodbye node-forever, hello pm2
- https://serversforhackers.com/editions/2014/11/04/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
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 3.0 (AGPL 3.0).
Except the file lib/CLI.js
who is made under the terms of the Apache V2 license.