PM2 – Quick Start

Welcome to the PM2 Quick Start!

PM2 is a daemon process manager that will help you manage and keep your application online. Getting started with PM2 is straightforward, it is offered as a simple and intuitive CLI, installable via NPM.

Installation

The latest PM2 version is installable with NPM or Yarn:

$ npm install pm2@latest -g
# or
$ yarn global add pm2

To install Node.js and NPM you can use NVM

Start an app

The simplest way to start, daemonize and monitor your application is by using this command line:

$ pm2 start app.js

Or start any other application easily:

$ pm2 start bashscript.sh
$ pm2 start python-app.py --watch
$ pm2 start binary-file -- --port 1520

Some options you can pass to the CLI:

# Specify an app name
--name <app_name>

# Watch and Restart app when files change
--watch

# Set memory threshold for app reload
--max-memory-restart <200MB>

# Specify log file
--log <log_path>

# Pass extra arguments to the script
-- arg1 arg2 arg3

# Delay between automatic restarts
--restart-delay <delay in ms>

# Prefix logs with time
--time

# Do not auto restart app
--no-autorestart

# Specify cron for forced restart
--cron <cron_pattern>

# Attach to application log
--no-daemon

As you can see many options are available to manage your application with PM2. You will discover them depending on your use case.

Managing processes

Managing application state is simple here are the commands:

$ pm2 restart app_name
$ pm2 reload app_name
$ pm2 stop app_name
$ pm2 delete app_name

Instead of app_name you can pass:

  • all to act on all processes
  • id to act on a specific process id

Check status, logs, metrics

Now that you have started this application, you can check his status, logs, metrics and even get the online dashboard with pm2.io.

List managed applications

List the status of all application managed by PM2:

$ pm2 [list|ls|status]
https://i1.wp.com/i.imgur.com/LmRD3FN.png?w=1500&ssl=1

Display logs

To display logs in realtime:

$ pm2 logs

To dig in older logs:

$ pm2 logs --lines 200

Terminal Based Dashboard

Here is a realtime dashboard that fits directly into your terminal:

$ pm2 monit
https://i0.wp.com/i.imgur.com/xo0LDb7.png?w=1500&ssl=1

pm2.io: Monitoring & Diagnostic Web Interface

Web based dashboard, cross servers with diagnostic system:

$ pm2 plus
https://i1.wp.com/i.imgur.com/sigMHli.png?w=1500&ssl=1

Cluster mode

For Node.js applications, PM2 includes an automatic load balancer that will share all HTTP[s]/Websocket/TCP/UDP connections between each spawned processes.

To start an application in Cluster mode:

$ pm2 start app.js -i max

Read more about cluster mode here.

Ecosystem File

You can also create a configuration file, called Ecosystem File, to manage multiple applications. To generate an Ecosystem file:

$ pm2 ecosystem

This will generate and ecosystem.config.js file:

module.exports = {
  apps : [{
    name: "app",
    script: "./app.js",
    env: {
      NODE_ENV: "development",
    },
    env_production: {
      NODE_ENV: "production",
    }
  }, {
     name: 'worker',
     script: 'worker.js'
  }]
}

And start it easily:

$ pm2 start process.yml

Read more about application declaration here.

Setup startup script

Restarting PM2 with the processes you manage on server boot/reboot is critical. To solve this, just run this command to generate an active startup script:

$ pm2 startup

And to freeze a process list for automatic respawn:

$ pm2 save

Read more about startup script generator here.

Restart application on changes

It’s pretty easy with the --watch option:

$ cd /path/to/my/app
$ pm2 start env.js --watch --ignore-watch="node_modules"

This will watch & restart the app on any file change from the current directory + all subfolders and it will ignore any changes in the node_modules folder --ignore-watch="node_modules".

You can then use pm2 logs to check for restarted app logs.

Updating PM2

We made it simple, there is no breaking change between releases and the procedure is straightforward:

npm install pm2@latest -g

Then update the in-memory PM2 :

pm2 update

CheatSheet

Here are some commands that are worth knowing. Just try them with a sample application or with your current web application on your development machine:

# 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.
pm2 scale app +3             # Scales `app` up by 3 workers
pm2 scale app 2              # Scales `app` up or down to 2 workers total

# 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 files
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 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

How to update PM2

Install the latest pm2 version:

npm install pm2@latest -g

Then update the in-memory PM2 :

pm2 update

PM2 – Managing applications states

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 you 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

NB: starting PM2 2.1.x, restarts are immutable, meaning that environment changes will not change your process, see –update-env

Now you want to delete the app from the PM2 process list. You just have to enter the following commands:

pm2 delete web-interface

Since PM2 2.4.0, you can also restart/delete/stop/reload applications via regex (this one will only restart http-1 and http-2 but not http-3):

pm2 restart /http-[1,2]/

Note : Regex are defined by leading and ending ‘/’ and they are tested against applications name only (not the process id).

Process listing

To list all running processes:

pm2 list
# Or
pm2 [list|ls|l|status]

To get more details about a specific process:

pm2 show 0

Process sorting

To sort all running processes:

pm2 list --sort name:desc
# Or
pm2 list --sort [name|id|pid|memory|cpu|status|uptime][:asc|desc]

By default sorting field is “name” and order is “asc”.

Start any process type

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"
}

Binary code execution

pm2 start ./binary-app

Process configuration

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"
  }]
}

Max Memory Restart

PM2 allows to restart an application based on a memory limit.

Note that the max memory restart options are graceful (if your application supports graceful actions of course).

CLI

pm2 start big-array.js --max-memory-restart 20M

JSON

{
  "name"   : "max_mem",
  "script" : "big-array.js",
  "max_memory_restart" : "20M"
}

Programmatic

pm2.start({
  name               : "max_mem",
  script             : "big-array.js",
  max_memory_restart : "20M"
}, function(err, proc) {
  // Processing
});

Units

Units can be K(ilobyte), M(egabyte), G(igabyte).

50M
50K
1G

PM2 Simple deploy

Getting started

PM2 embeds a simple and powerful deployment system with revision tracing. Another step by step tutorial here.

Please read the Considerations to use PM2 deploy.

Simple deploy

Baically you only need to add a “deploy” attribute to the ecosystem.json. Here is a bare minimum to deploy an application:

process.json:

{
   "apps" : [{
      "name" : "HTTP-API",
      "script" : "http.js"
   }],
   "deploy" : {
     // "production" is the environment name
     "production" : {
       "user" : "ubuntu",
       "host" : ["192.168.0.13"],
       "ref"  : "origin/master",
       "repo" : "git@github.com:Username/repository.git",
       "path" : "/var/www/my-repository",
       "post-deploy" : "npm install; grunt dist"
      },
   }
}

/bin/bash:

# Setup deployment at remote location
$ pm2 deploy production setup

# Update remote version
$ pm2 deploy production update

# Revert to -1 deployment
$ pm2 deploy production revert 1

# execute command on remote machines
$ pm2 deploy production exec "pm2 reload all"

Complete tutorial

1- Generate a sample ecosystem.json file that lists the processes and the deployment environment.

pm2 ecosystem

In the current folder a ecosystem.json file will be created. It contains this:

{
  // Applications part
  "apps" : [{
    "name"      : "API",
    "script"    : "app.js",
    "env": {
      "COMMON_VARIABLE": "true"
    },
    // Environment variables injected when starting with --env production
    // http://pm2.keymetrics.io/docs/usage/application-declaration/#switching-to-different-environments
    "env_production" : {
      "NODE_ENV": "production"
    }
  },{
    "name"      : "WEB",
    "script"    : "web.js"
  }],
  // Deployment part
  // Here you describe each environment
  "deploy" : {
    "production" : {
      "user" : "node",
      // Multi host is possible, just by passing IPs/hostname as an array
      "host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
      // Branch
      "ref"  : "origin/master",
      // Git repository to clone
      "repo" : "git@github.com:repo.git",
      // Path of the application on target servers
      "path" : "/var/www/production",
      // Can be used to give options in the format used in the configura-
      // tion file.  This is useful for specifying options for which there
      // is no separate command-line flag, see 'man ssh'
      // can be either a single string or an array of strings
      "ssh_options": "StrictHostKeyChecking=no",
      // To prepare the host by installing required software (eg: git)
      // even before the setup process starts
      // can be multiple commands separated by the character ";"
      // or path to a script on your local machine
      "pre-setup" : "apt-get install git",
      // Commands / path to a script on the host machine
      // This will be executed on the host after cloning the repository
      // eg: placing configurations in the shared dir etc
      "post-setup": "ls -la",
      // Commands to execute locally (on the same machine you deploy things)
      // Can be multiple commands separated by the character ";"
      "pre-deploy-local" : "echo 'This is a local executed command'"
      // Commands to be executed on the server after the repo has been cloned
      "post-deploy" : "npm install && pm2 startOrRestart ecosystem.json --env production"
      // Environment variables that must be injected in all applications on this env
      "env"  : {
        "NODE_ENV": "production"
      }
    },
    "staging" : {
      "user" : "node",
      "host" : "212.83.163.1",
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/development",
      "ssh_options": ["StrictHostKeyChecking=no", "PasswordAuthentication=no"],
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env dev",
      "env"  : {
        "NODE_ENV": "staging"
      }
    }
  }
}

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 node@myserver.com

If you encounter any errors, please refer to the troubleshooting section below.

3- Now initialize the remote folder with:

pm2 deploy <configuration_file> <environment> setup

Example:

pm2 deploy ecosystem.json production setup

This command will create 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 options

Display 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

Use different set of env variables

In the post-deploy attribute, you may have noticed the command pm2 startOrRestart ecosystem.json --env production. The --env <environment_name> allows to inject different sets of environment variables.

Read more here.

pm2 startOrRestart all.json            # Invoke restart on all apps in JSON
pm2 startOrReload all.json             # Invoke reload

Multi host deployment

To deploy to multiple hosts in the same time, you just have to declare each host in an array under the attribute host.

{
  [...]
  "deploy" : {
    "production" : {
      "user" : "node",
      // Multi host in a js array
      "host" : ["212.83.163.1", "212.83.163.2", "212.83.163.3"],
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/production",
      "pre-setup" : "echo 'commands or local script path to be run on the host before the setup process starts'",
      "post-setup": "echo 'commands or a script path to be run on the host after cloning the repo'",
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env production",
      "pre-deploy-local" : "echo 'This is a local executed command'"
    }
  [...]
}

Using SSH keys

You just have to add the “key” attribute with path to the public key, see below example :

    "production" : {
      "key"  : "/path/to/some.pem", // path to the public key to authenticate
      "user" : "node",              // user used to authenticate
      "host" : "212.83.163.1",      // where to connect
      "ref"  : "origin/master",
      "repo" : "git@github.com:repo.git",
      "path" : "/var/www/production",
      "post-deploy" : "pm2 startOrRestart ecosystem.json --env production"
    },

Force deployment

You may get this message:

--> Deploying to dev environment
--> on host 192.168.1.XX

  push your changes before deploying

Deploy failed

That means that you have changes in your local system that aren’t pushed inside your git repository, and since the deploy script get the update via git pull they will not be on your server. If you want to deploy without pushing any data, you can append the --force option:

pm2 deploy ecosystem.json production --force

Considerations

  • You can use the option --force to skip local change detection
  • You might want to commit your node_modules folder (#622) or add the npm install command to the post-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 variables depending on the environment you want to deploy the code to. For instance to declare variables for the production environment, add “env_production”: {} and declare the variables.
  • By default, PM2 will use ecosystem.json. So you can skip the options if this is 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
  • Processes are initialized / started automatically depending on the application name in ecosystem.json
  • PM2-deploy repository can be found here: pm2-deploy
  • WINDOWS : see point below (at the end)

Troubleshooting

SSH clone errors

In most cases, these errors will be caused by pm2 not having the correct keys to clone your repository. You need to verify at every step that the keys are available.

Step 1 If you are certain your keys are correctly working, first try running git clone your_repo.git on the target server. If it succeeds, move onto the next steps. If it failed, make sure your keys are stored both on the server and on your git account.

Step 2 By default ssh-copy-id copies the default identiy, usually named id_rsa. If that is not the appropriate key:

ssh-copy-id -i path/to/my/key your_username@server.com

This adds your public key to the ~/.ssh/authorized_keys file.

Step 3 If you get the following error:

--> Deploying to production environment
--> on host mysite.com
  ○ hook pre-setup
  ○ running setup
  ○ cloning git@github.com:user/repo.git
Cloning into '/var/www/app/source'...
Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights and that the repository exists.

**Failed to clone**

Deploy failed

…you may want to create a ssh config file. This is a sure way to ensure that the correct ssh keys are used for any given repository you’re trying to clone. See this example:

# ~/.ssh/config
Host alias
    HostName myserver.com
    User username
    IdentityFile ~/.ssh/mykey
# Usage: `ssh alias`
# Alternative: `ssh -i ~/.ssh/mykey username@myserver.com`

Host deployment
    HostName github.com
    User username
    IdentityFile ~/.ssh/github_rsa
# Usage:
# git@deployment:username/anyrepo.git
# This is for cloning any repo that uses that IdentityFile. This is a good way to make sure that your remote cloning commands use the appropriate key

Windows Consideration

To run the deploy script under Windows, you need to use a unix shell like bash, so we recommend to install either Git bashBabun or Cygwin

Updating PM2

To get the most out of PM2 and PM2.io, please make sure your PM2 version is up-to-date.

You can find the changelog here: https://github.com/Unitech/pm2/releases.

Updating PM2

Updating PM2 is extremely fast (less than few seconds) and seamless.

First make sure that you saved correctly all your processes:

pm2 save

Then install the latest PM2 version from NPM:

npm install pm2 -g

And finally update the in-memory PM2 process:

pm2 update

That’s all, you now have a fresh and up-to-date PM2 system!

Updating Startup Script

When you upgrade your Node.js version, the node binary path will change. To update the PM2 startup script run:

$ pm2 unstartup
$ pm2 startup

PM2 Max Memory Threshold Auto Reload

Max Memory Threshold Auto Reload

PM2 allows to reload (auto fallback to restart if not in cluster) an application based on a memory limit/ Please note that the PM2 internal worker (which checks memory), starts every 30 seconds, so you may have to wait a bit before your process gets restarted automatically after reaching the memory threshold.

CLI:

pm2 start api.js --max-memory-restart 300M

Config file (ecosystem.config.js):

module.exports = {
  apps: [{
    name: 'api',
    script: 'api.js',
    max_memory_restart: '300M'
  }]
}

Note: Units can be K(ilobyte), M(egabyte), G(igabyte).