Skip to content

Commit

Permalink
Merge pull request #1102 from Unitech/development
Browse files Browse the repository at this point in the history
v0.12.8 Release
  • Loading branch information
jshkurti committed Mar 17, 2015
2 parents cd7db9c + 62d43ef commit 14261fd
Show file tree
Hide file tree
Showing 25 changed files with 469 additions and 208 deletions.
2 changes: 1 addition & 1 deletion ADVANCED_README.md
Original file line number Diff line number Diff line change
Expand Up @@ -1454,7 +1454,7 @@ Don't use the *cluster_mode* via -i option.
<a name="a20"/>
## External resources and articles
- [Goodbye node-forever, hello pm2](http://devo.ps/blog/2013/06/26/goodbye-node-forever-hello-pm2.html)
- [Goodbye node-forever, hello pm2](http://devo.ps/blog/goodbye-node-forever-hello-pm2/)
- [https://serversforhackers.com/editions/2014/11/04/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
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,18 @@
# Coming Next

- `--no-vizion` flag : starts an app completely without vizion features
- `--no-restart` flag : starts PM2 without automatic restart feature
- dump/resurrect will leave 'stopped' apps as stopped instead of restarting every app

# 0.12.8 (Current Stabe)

- Fix : #1091
- Fix : `Channel closed error`
- Fix : `Resource leak error`
- New : When PM2 is being killed, all restarts are blocked to avoid conflict
- New : PM2 dumps the process list before exiting if it is killed by signal
- Refactored stop/restart for better stability

# 0.12.7

- pm2 logs : Now shows merged logs
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ Works on Linux (stable) & MacOSx (stable) & Windows (stable).

[![NPM version](https://badge.fury.io/js/pm2.png)](http://badge.fury.io/js/pm2) [![Gitter](https://badges.gitter.im/Join Chat.svg)] (https://gitter.im/Unitech/PM2?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Build Status](https://api.travis-ci.org/Unitech/PM2.png?branch=master)](https://travis-ci.org/Unitech/PM2) [![Inline docs](http://inch-ci.org/github/unitech/pm2.svg?branch=master)](http://inch-ci.org/github/unitech/pm2)


[![NPM](https://nodei.co/npm/pm2.png?downloads=true&downloadRank=true)](https://nodei.co/npm/pm2/)

## Install PM2
Expand Down
4 changes: 2 additions & 2 deletions bin/pm2
Original file line number Diff line number Diff line change
Expand Up @@ -536,8 +536,8 @@ commander.command('logs [id|name]')
.description('stream logs file. Default stream all logs')
.action(function(id, cmd) {
var line = 20;
if(typeof cmd.lines == 'number'){
line = cmd.lines;
if(!isNaN(cmd.lines)){
line = parseInt(cmd.lines);
}
CLI.streamLogs(id, line);
});
Expand Down
31 changes: 13 additions & 18 deletions doc/MODULE.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# Modules system

A PM2 module is basically a NPM module. But this time it's not a library, but a process that will be run with PM2.
A PM2 module is basically a NPM module. But this time it's not a library, but a process that will be runned with PM2.

Internally it embeds the NPM install procedure. So a PM2 module will be published to NPM and installed from NPM.

Expand All @@ -12,6 +12,7 @@ Internally it embeds the NPM install procedure. So a PM2 module will be publishe
```bash
$ pm2 install npm-module
$ pm2 uninstall npm-module
$ pm2 publish
```

Npm module can be a published npm package but can also be:
Expand All @@ -36,19 +37,21 @@ Publishing a module consist of doing:
$ npm publish
```

It will automatically increment the patch version and publish it to NPM.

## Development workflow

A workflow is available to easily develop new modules:
A workflow is available to easily develop new modules within the PM2 context

```bash
$ pm2 install .
$ pm2 logs
$ pm2 logs .
$ pm2 uninstall .
```

- Every time an update is made the module will be automatically restarted
- Use pm2 logs to see how your app behaves
- To debug what is send to pm2 just set the variable
- To debug what is send to pm2 just set the following variable:

```
process.env.MODULE_DEBUG = true;
Expand Down Expand Up @@ -90,38 +93,30 @@ An object can be passed to initModule:
}
```

These variables are accessible in the front end of Keymetrics.

## Configuration

```bash
$ pm2 set <npm-module.key> <value>
$ pm2 unset <npm-module.key>
$ pm2 set module:option_name <value>
$ pm2 unset module:option_name
```

The key will become an environment variable accessible inside the module or via the object returned by `pmx.initModule()`.

Example:

```bash
$ pm2 set 'server-monitoring.security' true
$ pm2 set server-monitoring:security true
```

Once you start the module called 'server-monitoring' you will be able to access to these custom variables:

```javascript
console.log(process.env.security);

// Or

var conf = pmx.initModule();

console.log(conf.security);
```

**NOTE** These variables are written in `~/.pm2/module_conf.json`, so if you prefer, you can directly edit these variables in this file.

## Internals

### Start

1- When a plugin is installed, it does an npm install and move it to .pm2/node_modules/module-name
-> pm2_env.pmx_module flag is set to true. Allows to differenciate it from other classic processes
**NOTE2** When you set a new value the target module is restarted
2 changes: 2 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@

var CLI = require('./lib/CLI.js');

process.env.PM2_PROGRAMMATIC = false;

/**
* Ensure that PM2 has been inited when using it programmatically
*/
Expand Down
83 changes: 66 additions & 17 deletions lib/CLI.js
Original file line number Diff line number Diff line change
Expand Up @@ -576,16 +576,18 @@ CLI.updatePM2 = function(cb) {
printOut('Be sure to have the latest version by doing `npm install pm2@latest -g` before doing this procedure.');

// Dump PM2 processes
Satan.executeRemote('notifyKillPM2', {}, function() {});
CLI.dump(function(err) {
debug('Dumping successfull', err);
CLI.killDaemon(function() {
debug('------------------ Everything killed', arguments);
Satan.launchDaemon(function(err, child) {
Satan.launchRPC(function() {
require('./Modularizer.js').launchAll();
CLI.resurrect(function() {
printOut(chalk.blue.bold('>>>>>>>>>> PM2 updated'));
return cb ? cb(null, {success:true}) : speedList();
require('./Modularizer.js').launchAll(function() {
return cb ? cb(null, {success:true}) : speedList();
});
});
});
});
Expand Down Expand Up @@ -769,6 +771,9 @@ CLI._reloadProcessName = function(process_name, reload_method, cb) {
});
};

/**
* Execute command with locking system
*/
CLI.remote = function(command, opts, cb) {
var proc_name = opts.name;

Expand Down Expand Up @@ -951,13 +956,16 @@ CLI._operate = function(action_name, process_name, envs, cb) {
async.eachLimit(ids, cst.CONCURRENT_ACTIONS, function(id, next) {
var opts = id;
if (action_name == 'restartProcessId') {
opts = { id : id, env : util._extend(process.env, envs) };
opts = {
id : id,
env : process.env.PM2_PROGRAMMATIC === true ? {} : util._extend(process.env, envs)
};
}

Satan.executeRemote(action_name, opts, function(err, res) {
if (err) {
printError(cst.PREFIX_MSG_ERR + 'Process %s not found', id);
return next(new Error('Process not found'));
return next('Process not found');
}

if (action_name == 'restartProcessId') {
Expand Down Expand Up @@ -1015,8 +1023,9 @@ CLI._operate = function(action_name, process_name, envs, cb) {
*/
if (full_detail && typeof(ids[0]) !== 'undefined' && full_detail[ids[0]] &&
full_detail[ids[0]].pm2_env && full_detail[ids[0]].pm2_env.pmx_module === true) {
var module_conf = Configuration.getAllSync();
util._extend(envs, module_conf);

var additional_env = Modularizer.getAdditionalConf(process_name);
util._extend(envs, additional_env);
}


Expand Down Expand Up @@ -1410,14 +1419,17 @@ CLI.ilogs = function() {
CLI.killDaemon = function(cb) {
printOut(cst.PREFIX_MSG + 'Stopping PM2...');

CLI._operate('deleteProcessId', 'all', function(err, list) {
printOut(cst.PREFIX_MSG + 'All processes has been stopped and deleted');
Satan.executeRemote('notifyKillPM2', {}, function() {});
CLI.killAllModules(function() {
CLI._operate('deleteProcessId', 'all', function(err, list) {
printOut(cst.PREFIX_MSG + 'All processes has been stopped and deleted');

InteractorDaemonizer.killDaemon(function(err, data) {
Satan.killDaemon(function(err, res) {
if (err) printError(err);
printOut(cst.PREFIX_MSG + 'PM2 stopped');
return cb ? cb(err, res) : exitCli(cst.SUCCESS_EXIT);
InteractorDaemonizer.killDaemon(function(err, data) {
Satan.killDaemon(function(err, res) {
if (err) printError(err);
printOut(cst.PREFIX_MSG + 'PM2 stopped');
return cb ? cb(err, res) : exitCli(cst.SUCCESS_EXIT);
});
});
});
});
Expand Down Expand Up @@ -1463,6 +1475,16 @@ CLI.publish = function(module_name, cb) {
});
};

CLI.killAllModules = function(cb) {
Common.getAllModulesId(function(err, modules_id) {
async.forEachLimit(modules_id, 1, function(id, next) {
CLI._operate('deleteProcessId', id, next);
}, function() {
return cb ? cb() : false;
});
});
};

CLI.deleteModule = function(module_name, cb) {
var found_proc = [];

Expand All @@ -1489,10 +1511,16 @@ CLI.deleteModule = function(module_name, cb) {
});
};

function displayConf(cb) {
printOut('\nCurrent values available');
function displayConf(target_app, cb) {
if (typeof(target_app) == 'function') {
cb = target_app;
target_app = null;
}

printOut('');

Configuration.getAll(function(err, data) {
UX.dispKeys(data);
UX.dispKeys(data, target_app);
return cb();
});
};
Expand All @@ -1503,7 +1531,28 @@ CLI.set = function(key, value, cb) {
return exitCli(cst.ERROR_EXIT);
}

displayConf(function() {
var values = [];

if (key.indexOf('.') > -1)
values = key.split('.');

if (key.indexOf(':') > -1)
values = key.split(':');

if (values && values.length > 1) {
// The first element is the app name (module_conf.json)
var app_name = values[0];

Common.printOut(cst.PREFIX_MSG + 'Restarting module %s', app_name);
CLI.restart(app_name, function(err, data) {
Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
displayConf(app_name, function() {
return exitCli(cst.SUCCESS_EXIT);
});
});
return false;
}
displayConf(app_name, function() {
return exitCli(cst.SUCCESS_EXIT);
});
});
Expand Down
33 changes: 21 additions & 12 deletions lib/CliUx.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,20 +163,29 @@ UX.dispAsTable = function(list, interact_infos) {
}
};

UX.dispKeys = function(kv) {
var app_table = new Table({
head: ['key', 'value'],
colAligns : ['left', 'left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
});

UX.dispKeys = function(kv, target_module) {
Object.keys(kv).forEach(function(key) {
var obj = {};
obj[key] = [kv[key]];
app_table.push(obj);
});

console.log(app_table.toString());
if (target_module != null && target_module != key)
return;

if (typeof(kv[key]) == 'object') {
var app_table = new Table({
head: ['key', 'value'],
colAligns : ['left', 'left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
});

var obj = {};

Object.keys(kv[key]).forEach(function(sub_key) {
obj[sub_key] = kv[key][sub_key];
app_table.push(obj);
});
console.log('== ' + chalk.bold.blue(key) + ' ==');
console.log(app_table.toString());
}
});
}

var defaultSpinnerString = '|/-\\';
Expand Down
24 changes: 21 additions & 3 deletions lib/Common.js
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ Common.exitCli = function(code) {
* @return CallExpression
*/
Common.printError = function(msg) {
if (process.env.PM2_SILENT) return false;
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC) return false;
if (msg instanceof Error)
return console.error(msg.message);
return console.error.apply(console, arguments);
Expand All @@ -178,10 +178,28 @@ Common.printError = function(msg) {
* @return
*/
Common.printOut = function() {
if (process.env.PM2_SILENT) return false;
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC) return false;
return console.log.apply(console, arguments);
};

Common.getAllModulesId = function(cb) {
var found_proc = [];

Satan.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}

list.forEach(function(proc) {
if (proc.pm2_env.pmx_module)
found_proc.push(proc.pm_id);
});

return cb(null, found_proc);
});
};

Common.getAllProcess = function(cb) {
var found_proc = [];

Expand Down Expand Up @@ -270,7 +288,7 @@ Common.extend = function(origin, add){
if (!add || typeof add != 'object') return origin;

//Ignore PM2's set environment variables from the nested env
var keysToIgnore = ['name', 'exec_mode', 'env', 'pm_cwd', 'exec_interpreter', 'pm_exec_path', 'node_args', 'pm_out_log_path', 'pm_err_log_path', 'pm_pid_path', 'pm_id', 'status', 'pm_uptime', 'created_at', 'started_inside', 'unstable_restarts', 'restart_time', 'pm_id', 'axm_actions'];
var keysToIgnore = ['name', 'exec_mode', 'env', 'pm_cwd', 'exec_interpreter', 'pm_exec_path', 'node_args', 'pm_out_log_path', 'pm_err_log_path', 'pm_pid_path', 'pm_id', 'status', 'pm_uptime', 'created_at', 'started_inside', 'unstable_restarts', 'restart_time', 'pm_id', 'axm_actions', 'pmx_module', 'command', 'watch', 'versioning', 'vizion_runing', 'MODULE_DEBUG'];

var keys = Object.keys(add);
var i = keys.length;
Expand Down
Loading

0 comments on commit 14261fd

Please sign in to comment.