PM (process manager)

Installation

PM is available only for linux due to heavy usage of linux mechanisms. Go to the releases page to download the latest binary.

# download binary
wget https://github.com/rprtr258/pm/releases/latest/download/pm_linux_amd64
# make binary executable
chmod +x pm_linux_amd64
# move binary to $PATH, here just local
mv pm_linux_amd64 pm

Systemd service

To enable running processes on system startup:

# soft link /usr/bin/pm binary to whenever it is installed
sudo ln -s ~/go/bin/pm /usr/bin/pm
# install systemd service, copy/paste output of following command
pm startup

After these commands, processes with startup: true config option will be started on system startup.

Configuration

PM supports multiple configuration formats for defining processes. The original jsonnet format is supported, along with several additional formats for flexibility:

Supported Formats

The primary configuration format. JSONNet is fully compatible with plain JSON.

[
  {
    name: "web-server",
    command: "node",
    args: ["server.js"],
    env: {
      PORT: "3000",
      NODE_ENV: "production"
    },
    tags: ["web"],
    startup: true
  }
]

YAML - Human-readable data serialization standard.

web-server:
  command: "node"
  args: ["server.js"]
  env:
    PORT: "3000"
    NODE_ENV: "production"
  tags: ["web"]
  startup: true

TOML - Tom's Obvious, Minimal Language configuration format.

[web-server]
command = "node"
args = ["server.js"]
env = { PORT = "3000", NODE_ENV = "production" }
tags = ["web"]
startup = true

Classic configuration file format with section-based structure.

[web-server]
command = node
args = server.js
env.PORT = 3000
env.NODE_ENV = production
tags = web
startup = true

HashiCorp Configuration Language, designed for human-readable machine-friendly configs.

process "web-server" {
  command = "node"
  args    = ["server.js"]
  env = {
    PORT     = "3000"
    NODE_ENV = "production"
  }
  tags    = ["web"]
  startup = true
}

Plain JSON configuration format.

[
  {
    "name": "web-server",
    "command": "node",
    "args": ["server.js"],
    "env": {
      "PORT": "3000",
      "NODE_ENV": "production"
    },
    "tags": ["web"],
    "startup": true
  }
]

Configuration Schema

All formats define list of processes with following fields:

FieldTypeDescriptionRequired
namestringProcess nameYes
commandstringCommand to executeYes
argsarray(string)Command argumentsNo
cwdstringWorking directoryNo
envmap(string, string)Environment variables (name: value pairs)No
tagsarray(string)Process tags for filteringNo
watchstringFile pattern to watch for restarts (regex)No
startupbooleanStart process on system startupNo
depends_onarray(string)Process names that must start firstNo
cronstringCron expression for scheduled executionNo
stdout_filestringFile to redirect stdout toNo
stderr_filestringFile to redirect stderr toNo
kill_timeoutdurationTime before SIGKILL after SIGINTNo
autorestartbooleanAuto-restart on process deathNo
max_restartsnumberMaximum restart limit (0 = unlimited)No

See example configuration file. Other examples can be found in tests directory.

Usage

Most fresh usage descriptions can be seen using pm <command> --help.

Run process

# run process using command
pm run go run main.go

# run processes from config file
pm run --config config.jsonnet

List processes

pm list

Start already added processes

pm start [ID/NAME/TAG]...

Stop processes

pm stop [ID/NAME/TAG]...

# e.g. stop all added processes (all processes has tag `all` by default)
pm stop all

Delete processes

When deleting process, they are first stopped, then removed from pm.

pm delete [ID/NAME/TAG]...

# e.g. delete all processes
pm delete all

Process state diagram

Running

new process

process started

process died

yes

no

start

stop

Stopped

Created

Running

autorestart/watch enabled?

Development

Architecture

pm consists of two parts:

  • cli client - requests server, launches/stops shim processes
  • shim - monitors and restarts processes, handle watches, signals and shutdowns

PM directory structure

pm uses XDG specification, so db and logs are in ~/.local/share/pm and config is ~/.config/pm.json. XDG_DATA_HOME and XDG_CONFIG_HOME environment variables can be used to change this. Layout is following:

~/.config/pm.json # pm config file
~/.local/share/pm/
├──db/ # database tables
│   └──<ID> # process info
└──logs/ # processes logs
    ├──<ID>.stdout # stdout of process with id ID
    └──<ID>.stderr # stderr of process with id ID

Differences from pm2

  • pm is just a single binary, not dependent on nodejs and bunch of js scripts
  • jsonnet configuration language, back compatible with JSON and allows to thoroughly configure processes, e.g. separate environments without requiring corresponding mechanism in pm (others configuration languages might be added in future such as Procfile, HCL, etc.)
  • supports only linux now
  • I can fix problems/add features as I need, independent of whether they work or not in pm2 because I don't know js
  • fast and convenient (I hope so)
  • no specific integrations for js

Release

On master branch:

git tag v1.2.3
git push --tags
GITHUB_TOKEN=<token> goreleaser release --clean