Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,54 @@ With the release of 0.11 pm2 no longer uses TCP sockets for the event bus, inste

Hopefully the pm2 team have a solution for this.

There is a way to temporarily solve the problem that remote hosts access local unix sockets: use socat!

Download socat to the machine that installed pm2:
- Ubuntu: `apt-get install socat`
- CentOS: `yum install socat`

Use a tcp port to forward the requests to the unix sockets (rpc.sock using port 6666 and pub.sock using port 6667):

```
socat "TCP-LISTEN:6666,reuseaddr,fork" "UNIX-CONNECT:$HOME/.pm2/rpc.sock"

socat "TCP-LISTEN:6667,reuseaddr,fork" "UNIX-CONNECT:$HOME/.pm2/pub.sock"
```

Tips: Path of UNIX-CONNECT cannot use ~, a **INCORRECT** example: UNIX-CONNECT:~/.pm2/rpc.sock

If you do not want to bind all IP (0.0.0.0), but bind specified (e.g. 192.168.1.10), there will be some trouble.

Because socat need to bind a local IP (127.0.0.1), and a bound IP, those IPs binding on different network adapter.

```
socat "TCP-LISTEN:6666,reuseaddr,fork,bind=192.168.1.10" "proxy:192.168.1.10:127.0.0.1:6666"
socat "TCP-LISTEN:6666,reuseaddr,fork,bind=127.0.0.1" "UNIX-CONNECT:$HOME/.pm2/rpc.sock"

socat "TCP-LISTEN:6667,reuseaddr,fork,bind=192.168.1.10" "proxy:192.168.1.10:127.0.0.1:6667"
socat "TCP-LISTEN:6667,reuseaddr,fork,bind=127.0.0.1" "UNIX-CONNECT:$HOME/.pm2/pub.sock"
```

End of the command to add '&', it will run in the background.

Then you need to modify pm2-web configuration file.

And host to the remote host IP, rpc and events from sock file path to the port number (Note: The port number is a number, non-string).
```
// To monitor multiple hosts, add extra entries to this array
"pm2": [{
"host": "localhost",
"rpc": "~/.pm2/rpc.sock",
"events": "~/.pm2/pub.sock"
},
{
"host": "192.168.1.10",
"rpc": 6666,
"events": 6667
}],
```


## Prerequisites

For debugging to work, [node-inspector](https://www.npmjs.org/package/node-inspector) must be installed and running on the same machine as pm2 (not necessarily the same as pm2-web).
Expand Down
4 changes: 2 additions & 2 deletions common/HostData.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ var HostData = function(data, config) {

this.name = data.name;
this.inspector = data.inspector;
this.pm2 = data.pm2,
this.pm2 = data.pm2;
this.system = {};
this.processes = [];
};
Expand Down Expand Up @@ -65,6 +65,6 @@ HostData.prototype.findProcessById = function(id) {
}

return null;
}
};

module.exports = HostData;
18 changes: 9 additions & 9 deletions common/ProcessData.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ var ProcessData = function(config, data) {
}

this._map(data);
}
};

ProcessData.prototype.update = function(data, system) {
this._map(data);

this._append((data.memory / system.memory.total) * 100, data.cpu, system.time);
}
};

ProcessData.prototype.log = function(type, data) {
if(!type || !data) {
Expand All @@ -44,21 +44,21 @@ ProcessData.prototype.log = function(type, data) {
if(this.logs.length > this._config.get("logs:max")) {
this.logs.splice(0, this.logs.length - this._config.get("logs:max"));
}
}
};

ProcessData.prototype._map = function(data) {
["id", "pid", "name", "script", "uptime", "restarts", "status", "memory", "cpu", "reloading", "debugPort", "mode"].forEach(function(key) {
this[key] = data[key];
}.bind(this));
}
};

ProcessData.prototype._append = function(memory, cpu, time) {
this.usage.memory = this._compressResourceUsage(this.usage.memory, time);
this.usage.cpu = this._compressResourceUsage(this.usage.cpu, time);

this._appendIfDifferent(this.usage.memory, memory, time);
this._appendIfDifferent(this.usage.cpu, cpu, time);
}
};

ProcessData.prototype._appendIfDifferent = function(array, value, time) {
var rounded = ~~value;
Expand All @@ -76,7 +76,7 @@ ProcessData.prototype._appendIfDifferent = function(array, value, time) {
x: time,
y: rounded
});
}
};

ProcessData.prototype._compressResourceUsage = function(data, time) {
var datapoints = this._config.get("graph:datapoints");
Expand Down Expand Up @@ -127,7 +127,7 @@ ProcessData.prototype._compressResourceUsage = function(data, time) {
}.bind(this));

return usage;
}
};

ProcessData.prototype._compressDay = function(day, now, datapoints, distribution) {
if(day.length == 0) {
Expand All @@ -143,7 +143,7 @@ ProcessData.prototype._compressDay = function(day, now, datapoints, distribution
var percent = distribution[dayDifference];

return this._compress(day, (datapoints/100) * percent);
}
};

ProcessData.prototype._compress = function(dataSet, maxSamples) {
var sampleSize = Math.ceil(dataSet.length/maxSamples);
Expand Down Expand Up @@ -181,6 +181,6 @@ ProcessData.prototype._compress = function(dataSet, maxSamples) {
}

return output;
}
};

module.exports = ProcessData;
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "pm2-web",
"version": "2.1.2",
"version": "2.1.3",
"description": "A web based monitor for PM2",
"preferGlobal": true,
"main": "pm2-web.js",
Expand All @@ -25,7 +25,7 @@
"cjson": "^0.3",
"minimist": "^1.0",
"semver": "^3.0",
"pwuid": "^1.0",
"path-extra": "^0.2.0",

"zepto-browserify": "^1.0",
"moment": "^2.5",
Expand Down
15 changes: 8 additions & 7 deletions server/app.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
var winston = require("winston"),
Container = require("wantsit").Container
Container = require("wantsit").Container,
Express = require("express"),
http = require("http"),
https = require("https"),
Expand All @@ -10,7 +10,7 @@ var winston = require("winston"),
fs = require("fs"),
methodOverride = require('method-override');

var REQUIRED_PM2_VERSION = "0.11.0";
var REQUIRED_PM2_VERSION = "0.12.0";

PM2Web = function(options) {
EventEmitter.call(this);
Expand Down Expand Up @@ -73,7 +73,7 @@ PM2Web = function(options) {
if (message == "shutdown") {
this.stop();
}
});
}.bind(this));

// make sure we shut down cleanly
process.on("exit", this.stop.bind(this));
Expand Down Expand Up @@ -118,7 +118,7 @@ PM2Web.prototype._createServer = function(express) {
}

return http.createServer(express);
}
};

PM2Web.prototype._createExpress = function() {
var config = this._container.find("config");
Expand All @@ -141,9 +141,10 @@ PM2Web.prototype._createExpress = function() {
express.use(Express.basicAuth(config.get("www:authentication:username"), config.get("www:authentication:password")));
}

express.use(Express.favicon(__dirname + "/public/img/favicon.png"));
express.use(Express.logger("dev"));
express.use(Express.urlencoded())
express.use(Express.json())
express.use(Express.urlencoded());
express.use(Express.json());
express.use(methodOverride('X-HTTP-Method')); // Microsoft
express.use(methodOverride('X-HTTP-Method-Override')); // Google/GData, default option
express.use(methodOverride('X-Method-Override')); // IBM
Expand All @@ -154,7 +155,7 @@ PM2Web.prototype._createExpress = function() {
express.use(Express.errorHandler());

return express;
}
};

PM2Web.prototype.setAddress = function(address) {
this._address = address;
Expand Down
34 changes: 16 additions & 18 deletions server/components/Configuration.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
var Autowire = require("wantsit").Autowire,
cjson = require("cjson"),
fs = require("fs"),
argv = require("minimist")(process.argv.slice(2)),
pwuid = require('pwuid');
argv = require("minimist")(process.argv.slice(2)),
userPath = require('path-extra');

var DEFAULT_CONFIG_FILE = __dirname + "/../../config.json";
var GLOBAL_CONFIG_FILE = "/etc/pm2-web/config.json";
Expand Down Expand Up @@ -37,7 +37,7 @@ var Configuration = function(options) {
this._override(options || {}, this._config);

this._normaliseHosts();
}
};

Configuration.prototype.afterPropertiesSet = function() {
// need to rethink this
Expand All @@ -56,7 +56,7 @@ Configuration.prototype.afterPropertiesSet = function() {

this._logger.info("Configuration", "Loaded default configuration from", DEFAULT_CONFIG_FILE);
this._logger.info("Configuration", "Final configuration:", JSON.stringify(config, null, 2));
}
};

Configuration.prototype._loadConfigFile = function() {
// try to find a config file
Expand All @@ -75,7 +75,7 @@ Configuration.prototype._loadConfigFile = function() {
}

return {};
}
};

Configuration.prototype._normaliseHosts = function() {
var args = this.get("pm2");
Expand Down Expand Up @@ -114,20 +114,18 @@ Configuration.prototype._normaliseHosts = function() {
args = [args];
}

var userDetails = pwuid()

// ensure data is correct for each host
args.forEach(function(host) {
host.host = host.host || "localhost";
host.rpc = host.rpc || "~/.pm2/rpc.sock";
host.events = host.events || "~/.pm2/pub.sock";

if(host.rpc.substring(0, 1) == "~") {
host.rpc = userDetails.dir + host.rpc.substring(1)
if(typeof host.rpc == 'string' && host.rpc.substring(0, 1) == "~") {
host.rpc = userPath.homedir() + host.rpc.substring(1)
}

if(host.events.substring(0, 1) == "~") {
host.events = userDetails.dir + host.events.substring(1)
if(typeof host.events == 'string' && host.events.substring(0, 1) == "~") {
host.events = userPath.homedir() + host.events.substring(1)
}

if(host.inspector === undefined) {
Expand All @@ -136,7 +134,7 @@ Configuration.prototype._normaliseHosts = function() {
});

this.set("pm2", args);
}
};

Configuration.prototype._arrayify = function(arg) {
if(!arg) {
Expand All @@ -148,7 +146,7 @@ Configuration.prototype._arrayify = function(arg) {
}

return [arg];
}
};

Configuration.prototype.get = function(key) {
if(!this._config || !key) {
Expand All @@ -166,15 +164,15 @@ Configuration.prototype.get = function(key) {
});

return value;
}
};

Configuration.prototype.set = function(key, value) {
if(!this._config || !key) {
return;
}

this._apply(key, value, this._config);
}
};

Configuration.prototype._apply = function(key, value, target) {
var parts;
Expand All @@ -196,7 +194,7 @@ Configuration.prototype._apply = function(key, value, target) {
target = target[property];
}
});
}
};

Configuration.prototype._defaults = function(object, defaults) {
if(typeof object == "undefined" || object == null) {
Expand Down Expand Up @@ -236,7 +234,7 @@ Configuration.prototype._defaults = function(object, defaults) {
}

this._logger.error("Configuration", "Don't know what to do with", object, "expected", defaults);
}
};

Configuration.prototype._override = function(source, target) {
Object.keys(source).forEach(function(key) {
Expand All @@ -256,6 +254,6 @@ Configuration.prototype._override = function(source, target) {
this._override(source[key], target[key]);
}
}.bind(this));
}
};

module.exports = Configuration;
Loading