Skip to content

Commit 14261fd

Browse files
committed
Merge pull request #1102 from Unitech/development
v0.12.8 Release
2 parents cd7db9c + 62d43ef commit 14261fd

25 files changed

Lines changed: 469 additions & 208 deletions

ADVANCED_README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1454,7 +1454,7 @@ Don't use the *cluster_mode* via -i option.
14541454
<a name="a20"/>
14551455
## External resources and articles
14561456
1457-
- [Goodbye node-forever, hello pm2](http://devo.ps/blog/2013/06/26/goodbye-node-forever-hello-pm2.html)
1457+
- [Goodbye node-forever, hello pm2](http://devo.ps/blog/goodbye-node-forever-hello-pm2/)
14581458
- [https://serversforhackers.com/editions/2014/11/04/pm2/](https://serversforhackers.com/editions/2014/11/04/pm2/)
14591459
- http://www.allaboutghost.com/keep-ghost-running-with-pm2/
14601460
- http://blog.ponyfoo.com/2013/09/19/deploying-node-apps-to-aws-using-grunt

CHANGELOG.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
# Coming Next
2+
3+
- `--no-vizion` flag : starts an app completely without vizion features
4+
- `--no-restart` flag : starts PM2 without automatic restart feature
5+
- dump/resurrect will leave 'stopped' apps as stopped instead of restarting every app
6+
7+
# 0.12.8 (Current Stabe)
8+
9+
- Fix : #1091
10+
- Fix : `Channel closed error`
11+
- Fix : `Resource leak error`
12+
- New : When PM2 is being killed, all restarts are blocked to avoid conflict
13+
- New : PM2 dumps the process list before exiting if it is killed by signal
14+
- Refactored stop/restart for better stability
15+
116
# 0.12.7
217

318
- pm2 logs : Now shows merged logs

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ Works on Linux (stable) & MacOSx (stable) & Windows (stable).
1010

1111
[![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)
1212

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

1516
## Install PM2

bin/pm2

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -536,8 +536,8 @@ commander.command('logs [id|name]')
536536
.description('stream logs file. Default stream all logs')
537537
.action(function(id, cmd) {
538538
var line = 20;
539-
if(typeof cmd.lines == 'number'){
540-
line = cmd.lines;
539+
if(!isNaN(cmd.lines)){
540+
line = parseInt(cmd.lines);
541541
}
542542
CLI.streamLogs(id, line);
543543
});

doc/MODULE.md

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
# Modules system
33

4-
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.
4+
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.
55

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

@@ -12,6 +12,7 @@ Internally it embeds the NPM install procedure. So a PM2 module will be publishe
1212
```bash
1313
$ pm2 install npm-module
1414
$ pm2 uninstall npm-module
15+
$ pm2 publish
1516
```
1617

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

40+
It will automatically increment the patch version and publish it to NPM.
41+
3942
## Development workflow
4043

41-
A workflow is available to easily develop new modules:
44+
A workflow is available to easily develop new modules within the PM2 context
4245

4346
```bash
4447
$ pm2 install .
45-
$ pm2 logs
48+
$ pm2 logs .
4649
$ pm2 uninstall .
4750
```
4851

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

5356
```
5457
process.env.MODULE_DEBUG = true;
@@ -90,38 +93,30 @@ An object can be passed to initModule:
9093
}
9194
```
9295

96+
These variables are accessible in the front end of Keymetrics.
97+
9398
## Configuration
9499

95100
```bash
96-
$ pm2 set <npm-module.key> <value>
97-
$ pm2 unset <npm-module.key>
101+
$ pm2 set module:option_name <value>
102+
$ pm2 unset module:option_name
98103
```
99104

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

102107
Example:
103108

104109
```bash
105-
$ pm2 set 'server-monitoring.security' true
110+
$ pm2 set server-monitoring:security true
106111
```
107112

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

110115
```javascript
111-
console.log(process.env.security);
112-
113-
// Or
114-
115116
var conf = pmx.initModule();
116117

117118
console.log(conf.security);
118119
```
119120

120121
**NOTE** These variables are written in `~/.pm2/module_conf.json`, so if you prefer, you can directly edit these variables in this file.
121-
122-
## Internals
123-
124-
### Start
125-
126-
1- When a plugin is installed, it does an npm install and move it to .pm2/node_modules/module-name
127-
-> pm2_env.pmx_module flag is set to true. Allows to differenciate it from other classic processes
122+
**NOTE2** When you set a new value the target module is restarted

index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11

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

4+
process.env.PM2_PROGRAMMATIC = false;
5+
46
/**
57
* Ensure that PM2 has been inited when using it programmatically
68
*/

lib/CLI.js

Lines changed: 66 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -576,16 +576,18 @@ CLI.updatePM2 = function(cb) {
576576
printOut('Be sure to have the latest version by doing `npm install pm2@latest -g` before doing this procedure.');
577577

578578
// Dump PM2 processes
579+
Satan.executeRemote('notifyKillPM2', {}, function() {});
579580
CLI.dump(function(err) {
580581
debug('Dumping successfull', err);
581582
CLI.killDaemon(function() {
582583
debug('------------------ Everything killed', arguments);
583584
Satan.launchDaemon(function(err, child) {
584585
Satan.launchRPC(function() {
585-
require('./Modularizer.js').launchAll();
586586
CLI.resurrect(function() {
587587
printOut(chalk.blue.bold('>>>>>>>>>> PM2 updated'));
588-
return cb ? cb(null, {success:true}) : speedList();
588+
require('./Modularizer.js').launchAll(function() {
589+
return cb ? cb(null, {success:true}) : speedList();
590+
});
589591
});
590592
});
591593
});
@@ -769,6 +771,9 @@ CLI._reloadProcessName = function(process_name, reload_method, cb) {
769771
});
770772
};
771773

774+
/**
775+
* Execute command with locking system
776+
*/
772777
CLI.remote = function(command, opts, cb) {
773778
var proc_name = opts.name;
774779

@@ -951,13 +956,16 @@ CLI._operate = function(action_name, process_name, envs, cb) {
951956
async.eachLimit(ids, cst.CONCURRENT_ACTIONS, function(id, next) {
952957
var opts = id;
953958
if (action_name == 'restartProcessId') {
954-
opts = { id : id, env : util._extend(process.env, envs) };
959+
opts = {
960+
id : id,
961+
env : process.env.PM2_PROGRAMMATIC === true ? {} : util._extend(process.env, envs)
962+
};
955963
}
956964

957965
Satan.executeRemote(action_name, opts, function(err, res) {
958966
if (err) {
959967
printError(cst.PREFIX_MSG_ERR + 'Process %s not found', id);
960-
return next(new Error('Process not found'));
968+
return next('Process not found');
961969
}
962970

963971
if (action_name == 'restartProcessId') {
@@ -1015,8 +1023,9 @@ CLI._operate = function(action_name, process_name, envs, cb) {
10151023
*/
10161024
if (full_detail && typeof(ids[0]) !== 'undefined' && full_detail[ids[0]] &&
10171025
full_detail[ids[0]].pm2_env && full_detail[ids[0]].pm2_env.pmx_module === true) {
1018-
var module_conf = Configuration.getAllSync();
1019-
util._extend(envs, module_conf);
1026+
1027+
var additional_env = Modularizer.getAdditionalConf(process_name);
1028+
util._extend(envs, additional_env);
10201029
}
10211030

10221031

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

1413-
CLI._operate('deleteProcessId', 'all', function(err, list) {
1414-
printOut(cst.PREFIX_MSG + 'All processes has been stopped and deleted');
1422+
Satan.executeRemote('notifyKillPM2', {}, function() {});
1423+
CLI.killAllModules(function() {
1424+
CLI._operate('deleteProcessId', 'all', function(err, list) {
1425+
printOut(cst.PREFIX_MSG + 'All processes has been stopped and deleted');
14151426

1416-
InteractorDaemonizer.killDaemon(function(err, data) {
1417-
Satan.killDaemon(function(err, res) {
1418-
if (err) printError(err);
1419-
printOut(cst.PREFIX_MSG + 'PM2 stopped');
1420-
return cb ? cb(err, res) : exitCli(cst.SUCCESS_EXIT);
1427+
InteractorDaemonizer.killDaemon(function(err, data) {
1428+
Satan.killDaemon(function(err, res) {
1429+
if (err) printError(err);
1430+
printOut(cst.PREFIX_MSG + 'PM2 stopped');
1431+
return cb ? cb(err, res) : exitCli(cst.SUCCESS_EXIT);
1432+
});
14211433
});
14221434
});
14231435
});
@@ -1463,6 +1475,16 @@ CLI.publish = function(module_name, cb) {
14631475
});
14641476
};
14651477

1478+
CLI.killAllModules = function(cb) {
1479+
Common.getAllModulesId(function(err, modules_id) {
1480+
async.forEachLimit(modules_id, 1, function(id, next) {
1481+
CLI._operate('deleteProcessId', id, next);
1482+
}, function() {
1483+
return cb ? cb() : false;
1484+
});
1485+
});
1486+
};
1487+
14661488
CLI.deleteModule = function(module_name, cb) {
14671489
var found_proc = [];
14681490

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

1492-
function displayConf(cb) {
1493-
printOut('\nCurrent values available');
1514+
function displayConf(target_app, cb) {
1515+
if (typeof(target_app) == 'function') {
1516+
cb = target_app;
1517+
target_app = null;
1518+
}
1519+
1520+
printOut('');
1521+
14941522
Configuration.getAll(function(err, data) {
1495-
UX.dispKeys(data);
1523+
UX.dispKeys(data, target_app);
14961524
return cb();
14971525
});
14981526
};
@@ -1503,7 +1531,28 @@ CLI.set = function(key, value, cb) {
15031531
return exitCli(cst.ERROR_EXIT);
15041532
}
15051533

1506-
displayConf(function() {
1534+
var values = [];
1535+
1536+
if (key.indexOf('.') > -1)
1537+
values = key.split('.');
1538+
1539+
if (key.indexOf(':') > -1)
1540+
values = key.split(':');
1541+
1542+
if (values && values.length > 1) {
1543+
// The first element is the app name (module_conf.json)
1544+
var app_name = values[0];
1545+
1546+
Common.printOut(cst.PREFIX_MSG + 'Restarting module %s', app_name);
1547+
CLI.restart(app_name, function(err, data) {
1548+
Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
1549+
displayConf(app_name, function() {
1550+
return exitCli(cst.SUCCESS_EXIT);
1551+
});
1552+
});
1553+
return false;
1554+
}
1555+
displayConf(app_name, function() {
15071556
return exitCli(cst.SUCCESS_EXIT);
15081557
});
15091558
});

lib/CliUx.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -163,20 +163,29 @@ UX.dispAsTable = function(list, interact_infos) {
163163
}
164164
};
165165

166-
UX.dispKeys = function(kv) {
167-
var app_table = new Table({
168-
head: ['key', 'value'],
169-
colAligns : ['left', 'left'],
170-
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
171-
});
172-
166+
UX.dispKeys = function(kv, target_module) {
173167
Object.keys(kv).forEach(function(key) {
174-
var obj = {};
175-
obj[key] = [kv[key]];
176-
app_table.push(obj);
177-
});
178168

179-
console.log(app_table.toString());
169+
if (target_module != null && target_module != key)
170+
return;
171+
172+
if (typeof(kv[key]) == 'object') {
173+
var app_table = new Table({
174+
head: ['key', 'value'],
175+
colAligns : ['left', 'left'],
176+
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
177+
});
178+
179+
var obj = {};
180+
181+
Object.keys(kv[key]).forEach(function(sub_key) {
182+
obj[sub_key] = kv[key][sub_key];
183+
app_table.push(obj);
184+
});
185+
console.log('== ' + chalk.bold.blue(key) + ' ==');
186+
console.log(app_table.toString());
187+
}
188+
});
180189
}
181190

182191
var defaultSpinnerString = '|/-\\';

lib/Common.js

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ Common.exitCli = function(code) {
166166
* @return CallExpression
167167
*/
168168
Common.printError = function(msg) {
169-
if (process.env.PM2_SILENT) return false;
169+
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC) return false;
170170
if (msg instanceof Error)
171171
return console.error(msg.message);
172172
return console.error.apply(console, arguments);
@@ -178,10 +178,28 @@ Common.printError = function(msg) {
178178
* @return
179179
*/
180180
Common.printOut = function() {
181-
if (process.env.PM2_SILENT) return false;
181+
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC) return false;
182182
return console.log.apply(console, arguments);
183183
};
184184

185+
Common.getAllModulesId = function(cb) {
186+
var found_proc = [];
187+
188+
Satan.executeRemote('getMonitorData', {}, function(err, list) {
189+
if (err) {
190+
Common.printError('Error retrieving process list: ' + err);
191+
return cb(err);
192+
}
193+
194+
list.forEach(function(proc) {
195+
if (proc.pm2_env.pmx_module)
196+
found_proc.push(proc.pm_id);
197+
});
198+
199+
return cb(null, found_proc);
200+
});
201+
};
202+
185203
Common.getAllProcess = function(cb) {
186204
var found_proc = [];
187205

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

272290
//Ignore PM2's set environment variables from the nested env
273-
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'];
291+
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'];
274292

275293
var keys = Object.keys(add);
276294
var i = keys.length;

0 commit comments

Comments
 (0)