Pm2 Prozess Manager Einführung

8 Minuten zum lesen

console.log('It´s time to code');

Hallo,

Heute möchte ich euch kurz den Prozessmanager PM2 vorstellen. Der mittels CLI Interface sehr komfortabel gesteuert werden kann.

image-center

Primäre Aufgaben eines Prozessmanagers:

  • Automatischer Neustart der Anwendung nach einem Absturz
  • Protokollierung im Fehlerfall
  • Monitorring des Laufzeitverhaltens und der Ressourcennutzung
  • Nachladen von Programmen ohne Ausfallzeit
  • uvm.

PM2 ist primär für den Einsatz in einer Produktivumgebung gedacht um bei einen Absturz einer Anwendung diese neu zu starten und den Fehler in einem Logfile festzuhalten. Gerade in der Releasephase einer Anwendung ist es von großen Vorteil das nicht jedes mal die Anwendung von Hand neu gestartet werden muss wenn ein Fehler auftritt.

PM2 unterstützt eine breite Palette von folgenden Skriptsprachen:

  • Javascript (Node.js)
  • Python
  • Ruby
  • uvm.

Installation

PM2 lässt sich ganz einfach über den Node Packet Manager (npm) mit folgenden Befehl installieren:

$ sudo npm install -g pm2

Nach der Installation prüfen wir noch ob PM2 auch ordnungsgemäß installiert worden ist mit folgenden Befehl:

$ pm2 

Und wir sollten folgende Ausgabe erhalten:

 Basic Examples:

    Start an app using all CPUs available + set a name :
    $ pm2 start app.js -i 0 --name "api"

    Restart the previous app launched, by name :
    $ pm2 restart api

    Stop the app :
    $ pm2 stop api

    Restart the app that is stopped :
    $ pm2 restart api

    Remove the app from the process list :
    $ pm2 delete api

    Kill daemon pm2 :
    $ pm2 kill

    Update pm2 :
    $ npm install pm2@latest -g ; pm2 update

    More examples in https://github.com/Unitech/pm2#usagefeatures

  Deployment help:

    $ pm2 deploy help

Erste Schritte mit PM2

Um einen Prozess über PM2 zu starten brauchen wir erst einmal ein kleines Skript. Dafür kopieren wir den unten angeführten Quellcode in einen Datei und geben ihr den Namen app.js.

var http = require('http');

var server = http.createServer(function (request, response) {
  response.writeHead(200, {"Content-Type": "text/plain"});
  response.end("Hello PM2\n");
  console.log(response.statusCode + ' ' + response.statusMessage);
}); 

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(8000);
console.log("Server running at http://127.0.0.1:8000/");

//app.js

Anschließend starten wie das Skript mit PM2 mit folgenden Befehl:

$ pm2 start app.js --name "app"
[PM2] Spawning PM2 daemon with pm2_home=/home/dgrill/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/dgrill/Schreibtisch/TEMP/app.js in fork_mode (1 instance)
[PM2] Done.
┌──────────┬────┬──────┬───────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid   │ status │ restart │ uptime │ cpu │ mem       │ watching │
├──────────┼────┼──────┼───────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ app      │ 0  │ fork │ 20211 │ online │ 0       │ 0s     │ 2%  │ 20.0 MB   │ disabled │
└──────────┴────┴──────┴───────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Und sehen in der Ausgabe das der Prozess nun erfolgreich gestartet worden ist.
Sollte unser kleine Anwendung nun einen Fehler produzieren wird der Prozess automatisch von PM2 neu gestartet und der restart counter erhöht. Des weiteren wird ein Eintrag im Error Log angelegt das Standardmässig unter linux im folgenden Verzeichnis zu finden ist (/home/user/.pm2/logs). Zusätzlich zum überwachen und neustarten von Prozessen zeichnet PM2 auch alle Logmeldungen auf, die von der Applikation in die Standard Ausgabe geschrieben werden.

/home/user/.pm2
├── logs
│   ├── app-error-0.log
│   └── app-out-0.log
├── module_conf.json
├── pids
│   └── app-0.pid
├── pm2.log
├── pm2.pid
├── pub.sock
├── rpc.sock
└── touch

2 directories, 9 files

Log Einträge anzeigen

Um sich die aktuellen Logmeldungen des laufenden Prozess live anzusehen geben wir folgenden Befehl ein:

$ pm2 logs app

Und wir erhalten folgende Ausgabe:

[STREAMING] Now streaming realtime logs for [app] process

Rufen wir nun in unseren Browser folgenden Link auf http://localhost:8000/ und senden somit eine Anfrage an unsere Applikation. Werden die Logmeldungen in Echtzeit ausgegeben.

0|app      | 200 OK 
0|app      | 200 OK 

Starten von Prozesse via config.json

Sollen mehrere Anwendungen von PM2 überwacht werden bittet es sich an alle Prozesse in eine json Datei zusammen zu fassen. Somit können mehrere Prozesse mit einen Befehl von PM2 überwacht werden.

[
{
  "script"    : "/home/dgrill/Schreibtisch/TEMP/app/app.js",
  "name"      : "app",
  "merge_logs"      : true,
  "log_date_format" : "YYYY-MM-DD HH:mm Z"
},
{
  "script"    : "/home/dgrill/Schreibtisch/TEMP/app_1/app_1.js",
  "name"      : "app_1",
  "merge_logs"      : true,
  "log_date_format" : "YYYY-MM-DD HH:mm Z"
}
]

process.json

Das Starten der Anwendung folgt wie schon oben beschrieben über den Befehl pm2 start nur mit dem Unterschied das wir hier die config.json datei angeben.

$ pm2 start process.json 
[PM2][WARN] Applications app, app_1 not running, starting...
[PM2] App [app] launched (1 instances)
[PM2] App [app_1] launched (1 instances)
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ app      │ 0  │ fork │ 2019 │ online │ 0       │ 0s     │ 0%  │ 17.2 MB   │ disabled │
│ app_1    │ 1  │ fork │ 2024 │ online │ 0       │ 0s     │ 0%  │ 16.6 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Neustarten der Prozesse

$ pm2 restart process.json 
[PM2] Applying action restartProcessId on app [app](ids: 0)
[PM2] Applying action restartProcessId on app [app_1](ids: 1)
[PM2] [app](0)[PM2] [app_1](1) ✓
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────────┤
│ app      │ 0  │ fork │ 7131 │ online │ 0       │ 10s    │ 0%  │ 17.3 MB   │ disabled │
│ app_1    │ 1  │ fork │ 7136 │ online │ 0       │ 10s    │ 0%  │ 15.2 MB   │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Stoppen der Prozesse

$ pm2 stop process.json 
[PM2] [app](0)[PM2] [app_1](1) ✓
┌──────────┬────┬──────┬─────┬─────────┬─────────┬────────┬─────┬────────┬──────────┐
│ App name │ id │ mode │ pid │ status  │ restart │ uptime │ cpu │ mem    │ watching │
├──────────┼────┼──────┼─────┼─────────┼─────────┼────────┼─────┼────────┼──────────┤
│ app      │ 0  │ fork │ 0   │ stopped │ 0       │ 12     │ 0%  │ 0 B    │ disabled │
│ app_1    │ 1  │ fork │ 0   │ stopped │ 0       │ 12     │ 0%  │ 0 B    │ disabled │
└──────────┴────┴──────┴─────┴─────────┴─────────┴────────┴─────┴────────┴──────────┘
 Use `pm2 show <id|name>` to get more details about an app

Der weitere große Vorteil von eine config.json datei ist das alle in diese enthalten Datei auf einmal gestartet/gestoppt oder neu gestartet werden können. Und somit auch Abhängigkeiten von Prozessen berücksichtigt werden können.

PM2 im produktiven Einsatz

Um nun PM2 produktiv einzusetzen müssen noch ein paar Grundeinstellungen vorgenommen werden. Als erstes müssen wie PM2 als dameon(bzw. Dienst) einrichten. Hierzu reicht uns erstmals folgender Befehl:

$ pm2 startup
[PM2] You have to run this command as root. Execute the following command:
      sudo su -c "env PATH=$PATH:/home/unitech/.nvm/versions/node/v4.3/bin pm2 startup <distribution> -u <user> --hp <home-path>

PM2 erstellt durch diesen Befehl automatisch ein Startscript für unser System und mit dem Befehl aus der Ausgabe wird das Startscript für den Systemstart registriert.

[PM2] Spawning PM2 daemon with pm2_home=/root/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Writing startup script in /etc/init.d/pm2-init.sh
[PM2] Making script booting at startup...
[PM2] -linux- Using the command:
      su -c "chmod +x /etc/init.d/pm2-init.sh && update-rc.d pm2-init.sh defaults"
[PM2] Done.

[PM2] Now you can type
$ pm2 save
[PM2] To save the current process list at reboot or via pm2 update

Wurde das Startskript erfolgreich im System registriert erhalten wir noch den Hinweise den Befehl pm2 save auszuführen.

$ pm2 save

Und das sollte wir auch auf alle Fälle tun wenn wir alle aktuellen prozesse speichern wollen und somit sicherstellen das nach einen Systemneustart alle Prozesse gestartet werden. Sollten wir das Speichern der Prozesse vergessen wird nach einen Systemneustart von PM2 kein Prozess gestartet. PM2 save muss auch jedes mal ausgeführt werden wenn wir einen neuen Prozess hinzufügen.

console.log('See you !');

Mehr Informationen

Eine Sammlung der Wichtigsten PM2 Befehle
PM2 Kommandoreferenz

Die offiziele Dokumentation von PM2
PM2 Official Docs

Aktualisiert: