Skip to content

Commit 382c52d

Browse files
committed
Merge pull request #1184 from Unitech/development
v0.12.11 release
2 parents 1d1d9fa + 2ddee3e commit 382c52d

51 files changed

Lines changed: 1039 additions & 200 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ADVANCED_README.md

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ $ pm2 updatePM2 # Update in memory pm2
143143
$ pm2 ping # Ensure pm2 daemon has been launched
144144
$ pm2 sendSignal SIGUSR2 my-app # Send system signal to script
145145
$ pm2 start app.js --no-daemon
146+
$ pm2 start app.js --no-vizion
147+
$ pm2 start app.js --no-autorestart
146148
```
147149

148150
## Different ways to launch a process
@@ -227,6 +229,8 @@ Options:
227229
--ignore-watch <folders|files> folder/files to be ignored watching, chould be a specific name or regex - e.g. --ignore-watch="test node_modules "some scripts""
228230
--node-args <node_args> space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"
229231
--no-color skip colors
232+
--no-vizion skip vizion features (versioning control)
233+
--no-autorestart do not automatically restart apps
230234
```
231235

232236

@@ -319,8 +323,8 @@ JSON:
319323

320324
Units can be K(ilobyte), M(egabyte), G(igabyte).
321325

322-
>
323-
Actually the way it works when you type :
326+
327+
Actually the way it works when you type:
324328
`pm2 start app.js --max-memory-restart 50M`
325329
commander module will transform it to `maxMemoryRestart: "50M"`, then after being processed by PM2 logic it will become an env variable as follows `max_memory_restart : 52428800 // in bytes this time`.
326330
But since programmatic interface doesn't use commander you have to give it raw-mode : `maxMemoryRestart`.
@@ -380,6 +384,12 @@ You can also reload all logs via the command line with:
380384
$ pm2 reloadLogs
381385
```
382386

387+
### Manually triggering garbage collection for PM2
388+
389+
```bash
390+
$ pm2 gc
391+
```
392+
383393
### Options
384394

385395
```bash
@@ -638,6 +648,8 @@ You can define parameters for your apps in `processes.json`:
638648
"log_date_format" : "YYYY-MM-DD HH:mm Z",
639649
"ignore_watch" : ["[\\/\\\\]\\./", "node_modules"],
640650
"watch" : true,
651+
"vizion" : true,
652+
"autorestart" : true,
641653
"node_args" : "--harmony",
642654
"cwd" : "/this/is/a/path/to/start/script",
643655
"env": {
@@ -718,6 +730,8 @@ Note that if you execute `pm2 start node-app-2` again, it will spawn an addition
718730
"merge_logs" : true,
719731
"exec_interpreter" : "node",
720732
"exec_mode" : "fork",
733+
"autorestart" : false, // enable/disable automatic restart when an app crashes or exits
734+
"vizion" : false, // enable/disable vizion features (versioning control)
721735
"env": {
722736
"NODE_ENV": "production",
723737
"AWESOME_SERVICE_API_TOKEN": "xxx"
@@ -1154,7 +1168,7 @@ pm2.connect(function(err) {
11541168
</tr>
11551169
<tr>
11561170
<td><b>Start</b></td>
1157-
<td>pm2.start(script_path|json_path, options, fn(err, proc){})</td>
1171+
<td>pm2.start(script_path|json_object|json_path, options, fn(err, proc){})</td>
11581172
</tr>
11591173
<tr>
11601174
<td>Options </td>

CHANGELOG.md

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,41 @@
11
# Coming Next
22

33
- `--no-logs` flag : doesn't save any logs (some people use their own logging system)
4-
- `--no-vizion` flag : starts an app completely without vizion features
5-
- `--no-restart` flag : starts PM2 without automatic restart feature
64
- dump/resurrect will leave 'stopped' apps as stopped instead of restarting every app
75
- YAML support for apps declarations
86
- Improve app declaration file parsing (log_file, out_file, error_file)
97

10-
# 0.12.10 (Current Stable)
8+
# 0.12.11 (Current stable)
9+
10+
- `--no-autorestart` flag : starts an app without automatic restart feature
11+
(`"autorestart" : false` in JSON declaration)
12+
13+
- `--no-vizion` flag : starts an app completely without vizion features
14+
(`"vizion" : false` in JSON declaration)
15+
16+
- Fix #1146 : add module._initPaths() on ProcessContainer.js so it forces each
17+
new process to take the current NODE_PATH env value in account
18+
19+
- New: pm2.start() now handles json objects as param
20+
21+
- Added: timestamps to KM agent logs
22+
23+
- Fix: now properly closes all fds after logging has finished.
24+
25+
- New command: pm2 gc (manually triggers garbage collection for PM2)
26+
27+
- VersioningManagment: exec() timeout configurable via .json
28+
29+
- Fix #1143 :
30+
If we start let's say 4 instances of an app (cluster_mode),
31+
Each app will have a value in process.env.NODE_APP_INSTANCE which will be 0 for the first one,
32+
1, 2 and 3 for the next ones.
33+
34+
- Fix #1154 :
35+
Negative arguments to '-i' are substracted to CPU cores number.
36+
E.g: 'pm2 start app.js -i -3' in a 8 cpus environment will start 5 instances (8 - 3).
37+
38+
# 0.12.10
1139

1240
- Fix : PM2 interactor doesn't send data about dead processes ('_old_') anymore.
1341
- Fix #1137 : Safe params for 'pm2 list' so cli-table won't fail

bin/pm2

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,16 @@ commander.version(pkg.version)
4444
.option('--ignore-watch <folders|files>', 'folder/files to be ignored watching, chould be a specific name or regex - e.g. --ignore-watch="test node_modules \"some scripts\""')
4545
.option('--node-args <node_args>', 'space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"')
4646
.option('--no-color', 'skip colors')
47+
.option('--no-vizion', 'start an app without vizion feature (versioning control)')
48+
.option('--no-autorestart', 'start an app without automatic restart')
49+
4750
.usage('[cmd] app');
4851

4952
commander.on('--help', function() {
5053
console.log(' Basic Examples:');
5154
console.log('');
5255
console.log(' Start an app using all CPUs available + set a name :');
53-
console.log(' $ pm2 start app.js -i max --name "api"');
56+
console.log(' $ pm2 start app.js -i 0 --name "api"');
5457
console.log('');
5558
console.log(' Restart the previous app launched, by name :');
5659
console.log(' $ pm2 restart api');
@@ -161,10 +164,10 @@ commander.command('start <file|json|stdin>')
161164
process.stdin.pause();
162165
CLI.startJson(cmd, commander, 'pipe');
163166
});
164-
} else if (cmd.slice(-5) == '.json')
165-
CLI.startJson(cmd, commander, 'file');
166-
else
167+
}
168+
else {
167169
CLI.start(cmd, commander);
170+
}
168171
});
169172

170173
commander.command('deploy <file|environment>')
@@ -594,6 +597,15 @@ commander.command('backward <name>')
594597
CLI.backward(pm2_name);
595598
});
596599

600+
//
601+
// Force PM2 to trigger garbage collection
602+
//
603+
commander.command('gc')
604+
.description('force PM2 to trigger garbage collection')
605+
.action(function() {
606+
CLI.forceGc();
607+
});
608+
597609
//
598610
// Catch all
599611
//

doc/DEBUG.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
2+
# List open files
3+
4+
```
5+
$ lsof -i -n -P | grep pm2
6+
```
7+
8+
Display limits
9+
10+
```
11+
$ ulimit -a
12+
```
13+
14+
# Memory leak
15+
16+
```
17+
require('webkit-devtools-agent').start({
18+
port: 9999,
19+
bind_to: '0.0.0.0',
20+
ipc_port: 3333,
21+
verbose: true
22+
});
23+
```
24+
25+
# Observe feature
26+
27+
```
28+
///////////////////////////////////////////////////////
29+
// Temporary disabling this because tests don't pass //
30+
///////////////////////////////////////////////////////
31+
32+
var obs = new observe.ObjectObserver(God.clusters_db);
33+
obs.open(function() {
34+
God.dumpProcessList && God.dumpProcessList(function() {
35+
console.log('Process List Dumped');
36+
});
37+
});
38+
if (!Object.observe) {
39+
setInterval(Platform.performMicrotaskCheckpoint, 1000);
40+
}
41+
```
42+
43+
# UncaughtException handling
44+
45+
```
46+
process.on('uncaughtException', function(err) {
47+
if (err && err.message == 'Resource leak detected.') {
48+
// Catch and ignore this error
49+
// Throw by cluster module with Node 0.11.13<=
50+
console.error(err.stack);
51+
console.error('Resource leak detected for cluster module');
52+
}
53+
else if (err) {
54+
console.error(err.stack);
55+
56+
if (God.dumpProcessList)
57+
God.dumpProcessList(function() {
58+
return process.exit(cst.ERROR_EXIT);
59+
});
60+
else
61+
return process.exit(cst.ERROR_EXIT);
62+
}
63+
});
64+
```

doc/PULL.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ or to the optional specified commit ID.
3636

3737
Everytime a backward/pull/forward command is executed, pm2 checks in ecosystem.json, process.json and package.json (in that order) for commands to run (e.g. npm install).
3838
The field should be named post_update and should be an array of commands.
39+
You can also set the timeout for exec() command with 'exec_timeout' field (in ms).
40+
By default it is 60000 (60sec).
3941
Your file should look something like this :
4042

4143
```json
@@ -50,7 +52,8 @@ Your file should look something like this :
5052
"script" : "app.js",
5153
"post_update" : ["echo App has been updated, running npm install...",
5254
"npm install",
53-
"echo App is being restarted now"]
55+
"echo App is being restarted now"],
56+
"exec_timeout" : 30000
5457
}
5558
]
5659
}

lib/CLI.js

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,29 @@ CLI.pm2Init = function() {
5959
}
6060
};
6161

62+
/**
63+
* Entry point to start an app / json file
64+
* keep retro-compat for startJson
65+
*/
66+
CLI.start = CLI.startJson = function(cmd, opts, cb) {
67+
if (typeof(opts) == "function") {
68+
cb = opts;
69+
opts = {};
70+
}
71+
72+
if ((typeof(cmd) === 'string' && cmd.indexOf('.json') != -1) || typeof(cmd) === 'object')
73+
CLI._startJson(cmd, opts, 'file', cb);
74+
else
75+
CLI._start(cmd, opts, cb);
76+
};
77+
6278
/**
6379
* Method to start a script
6480
* @method startFile
6581
* @param {string} script script name (will be resolved according to location)
6682
* @return
6783
*/
68-
CLI.start = function(script, opts, cb) {
84+
CLI._start = function(script, opts, cb) {
6985
if (typeof opts == "function") {
7086
cb = opts;
7187
opts = {};
@@ -319,7 +335,7 @@ CLI.actionFromJson = function(action, file, jsonVia, cb) {
319335
* @param {string} jsonVia
320336
* @param {function} cb
321337
*/
322-
CLI.startJson = function(cmd, opts, jsonVia, cb) {
338+
CLI._startJson = function(cmd, opts, jsonVia, cb) {
323339
var appConf, deployConf = null;
324340

325341
if (typeof(cb) === 'undefined' && typeof(jsonVia) === 'function')
@@ -382,7 +398,7 @@ CLI.startJson = function(cmd, opts, jsonVia, cb) {
382398
next();
383399
});
384400
}, function(err) {
385-
return cb ? cb(err, appConf) : speedList();
401+
return cb ? cb(err || null, appConf) : speedList();
386402
});
387403
};
388404

@@ -760,7 +776,7 @@ CLI._reloadProcessName = function(process_name, reload_method, cb) {
760776

761777
Satan.notifyGod('restart', proc.pm2_env.pm_id);
762778

763-
return CLI._restart(process_name, next);
779+
return CLI.restart(process_name, next);
764780
}
765781

766782
Satan.executeRemote(reload_method, proc.pm2_env.pm_id, function(err, res) {
@@ -1231,7 +1247,7 @@ CLI.describe = function(pm2_id, cb) {
12311247
});
12321248

12331249
if (found_proc.length === 0) {
1234-
printError('%s doesn\'t exist', pm2_id);
1250+
printError(cst.PREFIX_MSG_WARNING + '%s doesn\'t exist', pm2_id);
12351251
return cb ? cb(null, []) : exitCli(cst.ERROR_EXIT);
12361252
}
12371253

@@ -1638,7 +1654,7 @@ var Version = require('./tools/VersionManagement.js');
16381654
* @return
16391655
*/
16401656
CLI.pullAndRestart = function (process_name, cb) {
1641-
Version._pull({process_name: process_name, action: 'restart'}, cb);
1657+
Version._pull({process_name: process_name, action: 'reload'}, cb);
16421658
};
16431659

16441660
/**
@@ -1687,6 +1703,24 @@ CLI.backward = Version.backward;
16871703
*/
16881704
CLI.forward = Version.forward;
16891705

1706+
1707+
/**
1708+
* CLI method for triggering garbage collection manually
1709+
* @method forcegc
1710+
* @return
1711+
*/
1712+
CLI.forceGc = function() {
1713+
Satan.executeRemote('forceGc', {}, function(err, data) {
1714+
if (data && data.success === false) {
1715+
printError(cst.PREFIX_MSG_ERR + 'Garbage collection failed');
1716+
exitCli(cst.ERRO_EXIT);
1717+
} else {
1718+
printOut(cst.PREFIX_MSG + 'Garbage collection manually triggered');
1719+
exitCli(cst.SUCCESS_EXIT);
1720+
}
1721+
});
1722+
};
1723+
16901724
//
16911725
// Private methods
16921726
//
@@ -1932,10 +1966,10 @@ function checkDeprecates(conf){
19321966
conf.instances = parseInt(conf.instances) || 0;
19331967

19341968
// Ensure instance param is not a negative value
1935-
if (conf.instances < 0) {
1936-
warn('You passed a negative value to indicate the number of instances... Setting this to maximum instances.');
1937-
conf.instances = 0;
1938-
}
1969+
// if (conf.instances < 0) {
1970+
// warn('You passed a negative value to indicate the number of instances... Setting this to maximum instances.');
1971+
// conf.instances = 0;
1972+
// }
19391973
}
19401974

19411975
/**

lib/Common.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,15 +108,23 @@ Common.prepareAppConf = function(app, cwd, outputter) {
108108
var formated_app_name = app.name.replace(/[^a-zA-Z0-9\\.\\-]/g, '-');
109109

110110
['log', 'out', 'error', 'pid'].forEach(function(f){
111+
111112
var af = app[f + '_file'], ps, ext = (f == 'pid' ? 'pid':'log'), isStd = !~['log', 'pid'].indexOf(f);
112-
if((f == 'log' && typeof af == 'boolean' && af) || (f != 'log' && !af)){
113+
if ((f == 'log' && typeof af == 'boolean' && af) || (f != 'log' && !af)) {
113114
ps = [cst['DEFAULT_' + ext.toUpperCase() + '_PATH'], formated_app_name + (isStd ? '-' + f : '') + '.' + ext];
114-
}else if(f != 'log' || (f == 'log' && af)){
115+
} else if (f != 'log' || (f == 'log' && af)) {
115116
ps = [cwd, af];
117+
118+
if (!fs.existsSync(path.dirname(af))) {
119+
Common.printError(cst.PREFIX_MSG_ERR + 'Folder does not exists: ' + path.dirname(af));
120+
throw new Error('Folder does not exists');
121+
}
122+
116123
}
117124
// PM2 paths
118125
ps && (app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = p.resolve.apply(null, ps));
119126
delete app[f + '_file']
127+
120128
});
121129

122130
//set port env variable

0 commit comments

Comments
 (0)