UNPKG

29.4 kBPlain TextView Raw
1#!/usr/bin/env node
2'use strict';
3
4var semver = require('semver');
5
6if (semver.satisfies(process.versions.node, '>= 6.0.0'))
7 require('v8-compile-cache');
8
9process.env.PM2_USAGE = 'CLI';
10
11var cst = require('../constants.js');
12
13var commander = require('commander');
14var chalk = require('chalk');
15var forEachLimit = require('async/forEachLimit');
16
17var debug = require('debug')('pm2:cli');
18var PM2 = require('../lib/API.js');
19var pkg = require('../package.json');
20var tabtab = require('../lib/completion.js');
21var Common = require('../lib/Common.js');
22var PM2ioHandler = require('../lib/API/pm2-plus/PM2IO')
23
24
25Common.determineSilentCLI();
26Common.printVersion();
27
28var pm2 = new PM2();
29
30PM2ioHandler.usePM2Client(pm2)
31
32commander.version(pkg.version)
33 .option('-v --version', 'print pm2 version')
34 .option('-s --silent', 'hide all messages', false)
35 .option('--ext <extensions>', 'watch only this file extensions')
36 .option('-n --name <name>', 'set a name for the process in the process list')
37 .option('-m --mini-list', 'display a compacted list without formatting')
38 .option('--interpreter <interpreter>', 'set a specific interpreter to use for executing app, default: node')
39 .option('--interpreter-args <arguments>', 'set arguments to pass to the interpreter (alias of --node-args)')
40 .option('--node-args <node_args>', 'space delimited arguments to pass to node')
41 .option('-o --output <path>', 'specify log file for stdout')
42 .option('-e --error <path>', 'specify log file for stderr')
43 .option('-l --log [path]', 'specify log file which gathers both stdout and stderr')
44 .option('--log-type <type>', 'specify log output style (raw by default, json optional)')
45 .option('--log-date-format <date format>', 'add custom prefix timestamp to logs')
46 .option('--time', 'enable time logging')
47 .option('--disable-logs', 'disable all logs storage')
48 .option('--env <environment_name>', 'specify which set of environment variables from ecosystem file must be injected')
49 .option('-a --update-env', 'force an update of the environment with restart/reload (-a <=> apply)')
50 .option('-f --force', 'force actions')
51 .option('-i --instances <number>', 'launch [number] instances (for networked app)(load balanced)')
52 .option('--parallel <number>', 'number of parallel actions (for restart/reload)')
53 .option('-p --pid <pid>', 'specify pid file')
54 .option('-k --kill-timeout <delay>', 'delay before sending final SIGKILL signal to process')
55 .option('--listen-timeout <delay>', 'listen timeout on application reload')
56 .option('--max-memory-restart <memory>', 'Restart the app if an amount of memory is exceeded (in bytes)')
57 .option('--restart-delay <delay>', 'specify a delay between restarts (in milliseconds)')
58 .option('--exp-backoff-restart-delay <delay>', 'specify a delay between restarts (in milliseconds)')
59 .option('-x --execute-command', 'execute a program using fork system')
60 .option('--max-restarts [count]', 'only restart the script COUNT times')
61 .option('-u --user <username>', 'define user when generating startup script')
62 .option('--uid <uid>', 'run target script with <uid> rights')
63 .option('--gid <gid>', 'run target script with <gid> rights')
64 .option('--cwd <path>', 'run target script as <username>')
65 .option('--hp <home path>', 'define home path when generating startup script')
66 .option('--wait-ip', 'override systemd script to wait for full internet connectivity to launch pm2')
67 .option('--service-name <name>', 'define service name when generating startup script')
68 .option('-c --cron <cron_pattern>', 'restart a running process based on a cron pattern')
69 .option('-w --write', 'write configuration in local folder')
70 .option('--no-daemon', 'run pm2 daemon in the foreground if it doesn\'t exist already')
71 .option('--source-map-support', 'force source map support')
72 .option('--only <application-name>', 'with json declaration, allow to only act on one application')
73 .option('--disable-source-map-support', 'force source map support')
74 .option('--wait-ready', 'ask pm2 to wait for ready event from your app')
75 .option('--merge-logs', 'merge logs from different instances but keep error and out separated')
76 .option('--watch [paths]', 'watch application folder for changes', function(v, m) { m.push(v); return m;}, [])
77 .option('--ignore-watch <folders|files>', 'List of paths to ignore (name or regex)')
78 .option('--watch-delay <delay>', 'specify a restart delay after changing files (--watch-delay 4 (in sec) or 4000ms)')
79 .option('--no-color', 'skip colors')
80 .option('--no-vizion', 'start an app without vizion feature (versioning control)')
81 .option('--no-autorestart', 'start an app without automatic restart')
82 .option('--no-treekill', 'Only kill the main process, not detached children')
83 .option('--no-pmx', 'start an app without pmx')
84 .option('--no-automation', 'start an app without pmx')
85 .option('--trace', 'enable transaction tracing with km')
86 .option('--disable-trace', 'disable transaction tracing with km')
87 .option('--attach', 'attach logging after your start/restart/stop/reload')
88 .option('--sort <field_name:sort>', 'sort process according to field\'s name')
89 .option('--v8', 'enable v8 data collecting')
90 .option('--event-loop-inspector', 'enable event-loop-inspector dump in pmx')
91 .option('--deep-monitoring', 'enable all monitoring tools (equivalent to --v8 --event-loop-inspector --trace)')
92 .usage('[cmd] app');
93
94function displayUsage() {
95 console.log('usage: pm2 [options] <command>')
96 console.log('');
97 console.log('pm2 -h, --help all available commands and options');
98 console.log('pm2 examples display pm2 usage examples');
99 console.log('pm2 <command> -h help on a specific command');
100 console.log('');
101 console.log('Access pm2 files in ~/.pm2');
102}
103
104function displayExamples() {
105 console.log('- Start and add a process to the pm2 process list:')
106 console.log('');
107 console.log(chalk.cyan(' $ pm2 start app.js --name app'));
108 console.log('');
109 console.log('- Show the process list:');
110 console.log('');
111 console.log(chalk.cyan(' $ pm2 ls'));
112 console.log('');
113 console.log('- Stop and delete a process from the pm2 process list:');
114 console.log('');
115 console.log(chalk.cyan(' $ pm2 delete app'));
116 console.log('');
117 console.log('- Stop, start and restart a process from the process list:');
118 console.log('');
119 console.log(chalk.cyan(' $ pm2 stop app'));
120 console.log(chalk.cyan(' $ pm2 start app'));
121 console.log(chalk.cyan(' $ pm2 restart app'));
122 console.log('');
123 console.log('- Clusterize an app to all CPU cores available:');
124 console.log('');
125 console.log(chalk.cyan(' $ pm2 start -i max'));
126 console.log('');
127 console.log('- Update pm2 :');
128 console.log('');
129 console.log(chalk.cyan(' $ npm install pm2 -g && pm2 update'));
130 console.log('');
131 console.log('- Install pm2 auto completion:')
132 console.log('');
133 console.log(chalk.cyan(' $ pm2 completion install'))
134 console.log('');
135 console.log('Check the full documentation on https://pm2.io/doc');
136 console.log('');
137}
138
139function beginCommandProcessing() {
140 pm2.getVersion(function(err, remote_version) {
141 if (!err && (pkg.version != remote_version)) {
142 console.log('');
143 console.log(chalk.red.bold('>>>> In-memory PM2 is out-of-date, do:\n>>>> $ pm2 update'));
144 console.log('In memory PM2 version:', chalk.blue.bold(remote_version));
145 console.log('Local PM2 version:', chalk.blue.bold(pkg.version));
146 console.log('');
147 }
148 });
149 commander.parse(process.argv);
150}
151
152function checkCompletion(){
153 return tabtab.complete('pm2', function(err, data) {
154 if(err || !data) return;
155 if(/^--\w?/.test(data.last)) return tabtab.log(commander.options.map(function (data) {
156 return data.long;
157 }), data);
158 if(/^-\w?/.test(data.last)) return tabtab.log(commander.options.map(function (data) {
159 return data.short;
160 }), data);
161 // array containing commands after which process name should be listed
162 var cmdProcess = ['stop', 'restart', 'scale', 'reload', 'delete', 'reset', 'pull', 'forward', 'backward', 'logs', 'describe', 'desc', 'show'];
163
164 if (cmdProcess.indexOf(data.prev) > -1) {
165 pm2.list(function(err, list){
166 tabtab.log(list.map(function(el){ return el.name }), data);
167 pm2.disconnect();
168 });
169 }
170 else if (data.prev == 'pm2') {
171 tabtab.log(commander.commands.map(function (data) {
172 return data._name;
173 }), data);
174 pm2.disconnect();
175 }
176 else
177 pm2.disconnect();
178 });
179};
180
181var _arr = process.argv.indexOf('--') > -1 ? process.argv.slice(0, process.argv.indexOf('--')) : process.argv;
182
183if (_arr.indexOf('log') > -1) {
184 process.argv[_arr.indexOf('log')] = 'logs';
185}
186
187if (_arr.indexOf('--no-daemon') > -1) {
188 //
189 // Start daemon if it does not exist
190 //
191 // Function checks if --no-daemon option is present,
192 // and starts daemon in the same process if it does not exist
193 //
194 console.log('pm2 launched in no-daemon mode (you can add DEBUG="*" env variable to get more messages)');
195
196 var pm2NoDaeamon = new PM2({
197 daemon_mode : false
198 });
199
200 pm2NoDaeamon.connect(function() {
201 pm2 = pm2NoDaeamon;
202 beginCommandProcessing();
203 });
204
205}
206else if (_arr.indexOf('startup') > -1 || _arr.indexOf('unstartup') > -1) {
207 setTimeout(function() {
208 commander.parse(process.argv);
209 }, 100);
210}
211else {
212 // HERE we instanciate the Client object
213 pm2.connect(function() {
214 debug('Now connected to daemon');
215 if (process.argv.slice(2)[0] === 'completion') {
216 checkCompletion();
217 //Close client if completion related installation
218 var third = process.argv.slice(3)[0];
219 if ( third == null || third === 'install' || third === 'uninstall')
220 pm2.disconnect();
221 }
222 else {
223 beginCommandProcessing();
224 }
225 });
226}
227
228//
229// Helper function to fail when unknown command arguments are passed
230//
231function failOnUnknown(fn) {
232 return function(arg) {
233 if (arguments.length > 1) {
234 console.log(cst.PREFIX_MSG + '\nUnknown command argument: ' + arg);
235 commander.outputHelp();
236 process.exit(cst.ERROR_EXIT);
237 }
238 return fn.apply(this, arguments);
239 };
240}
241
242/**
243 * @todo to remove at some point once it's fixed in official commander.js
244 * https://github.com/tj/commander.js/issues/475
245 *
246 * Patch Commander.js Variadic feature
247 */
248function patchCommanderArg(cmd) {
249 var argsIndex;
250 if ((argsIndex = commander.rawArgs.indexOf('--')) >= 0) {
251 var optargs = commander.rawArgs.slice(argsIndex + 1);
252 cmd = cmd.slice(0, cmd.indexOf(optargs[0]));
253 }
254 return cmd;
255}
256
257//
258// Start command
259//
260commander.command('start [name|file|ecosystem|id...]')
261 .option('--watch', 'Watch folder for changes')
262 .option('--fresh', 'Rebuild Dockerfile')
263 .option('--daemon', 'Run container in Daemon mode (debug purposes)')
264 .option('--container', 'Start application in container mode')
265 .option('--dist', 'with --container; change local Dockerfile to containerize all files in current directory')
266 .option('--image-name [name]', 'with --dist; set the exported image name')
267 .option('--node-version [major]', 'with --container, set a specific major Node.js version')
268 .option('--dockerdaemon', 'for debugging purpose')
269 .description('start and daemonize an app')
270 .action(function(cmd, opts) {
271 if (opts.container == true && opts.dist == true)
272 return pm2.dockerMode(cmd, opts, 'distribution');
273 else if (opts.container == true)
274 return pm2.dockerMode(cmd, opts, 'development');
275
276 if (cmd == "-") {
277 process.stdin.resume();
278 process.stdin.setEncoding('utf8');
279 process.stdin.on('data', function (cmd) {
280 process.stdin.pause();
281 pm2._startJson(cmd, commander, 'restartProcessId', 'pipe');
282 });
283 }
284 else {
285 // Commander.js patch
286 cmd = patchCommanderArg(cmd);
287 if (cmd.length === 0) {
288 cmd = [cst.APP_CONF_DEFAULT_FILE];
289 }
290 forEachLimit(cmd, 1, function(script, next) {
291 pm2.start(script, commander, next);
292 }, function(err) {
293 pm2.speedList(err ? 1 : 0);
294 });
295 }
296 });
297
298commander.command('trigger <proc_name> <action_name> [params]')
299 .description('trigger process action')
300 .action(function(pm_id, action_name, params) {
301 pm2.trigger(pm_id, action_name, params);
302 });
303
304commander.command('deploy <file|environment>')
305 .description('deploy your json')
306 .action(function(cmd) {
307 pm2.deploy(cmd, commander);
308 });
309
310commander.command('startOrRestart <json>')
311 .description('start or restart JSON file')
312 .action(function(file) {
313 pm2._startJson(file, commander, 'restartProcessId');
314 });
315
316commander.command('startOrReload <json>')
317 .description('start or gracefully reload JSON file')
318 .action(function(file) {
319 pm2._startJson(file, commander, 'reloadProcessId');
320 });
321
322commander.command('pid [app_name]')
323 .description('return pid of [app_name] or all')
324 .action(function(app) {
325 pm2.getPID(app);
326 });
327
328commander.command('startOrGracefulReload <json>')
329 .description('start or gracefully reload JSON file')
330 .action(function(file) {
331 pm2._startJson(file, commander, 'softReloadProcessId');
332 });
333
334//
335// Stop specific id
336//
337commander.command('stop <id|name|all|json|stdin...>')
338 .option('--watch', 'Stop watching folder for changes')
339 .description('stop a process')
340 .action(function(param) {
341 forEachLimit(param, 1, function(script, next) {
342 pm2.stop(script, next);
343 }, function(err) {
344 pm2.speedList(err ? 1 : 0);
345 });
346 });
347
348//
349// Stop All processes
350//
351commander.command('restart <id|name|all|json|stdin...>')
352 .option('--watch', 'Toggle watching folder for changes')
353 .description('restart a process')
354 .action(function(param) {
355 // Commander.js patch
356 param = patchCommanderArg(param);
357 forEachLimit(param, 1, function(script, next) {
358 pm2.restart(script, commander, next);
359 }, function(err) {
360 pm2.speedList(err ? 1 : 0);
361 });
362 });
363
364//
365// Scale up/down a process in cluster mode
366//
367commander.command('scale <app_name> <number>')
368 .description('scale up/down a process in cluster mode depending on total_number param')
369 .action(function(app_name, number) {
370 pm2.scale(app_name, number);
371 });
372
373//
374// snapshot PM2
375//
376commander.command('profile:mem [time]')
377 .description('Sample PM2 heap memory')
378 .action(function(time) {
379 pm2.profile('mem', time);
380 });
381
382//
383// snapshot PM2
384//
385commander.command('profile:cpu [time]')
386 .description('Profile PM2 cpu')
387 .action(function(time) {
388 pm2.profile('cpu', time);
389 });
390
391//
392// Reload process(es)
393//
394commander.command('reload <name|all>')
395 .description('reload processes (note that its for app using HTTP/HTTPS)')
396 .action(function(pm2_id) {
397 pm2.reload(pm2_id, commander);
398 });
399
400commander.command('id <name>')
401 .description('get process id by name')
402 .action(function(name) {
403 pm2.getProcessIdByName(name);
404 });
405
406// Inspect a process
407commander.command('inspect <name>')
408 .description('inspect a process')
409 .action(function(cmd) {
410 pm2.inspect(cmd, commander);
411 });
412
413//
414// Stop and delete a process by name from database
415//
416commander.command('delete <name|id|script|all|json|stdin...>')
417 .alias('del')
418 .description('stop and delete a process from pm2 process list')
419 .action(function(name) {
420 if (name == "-") {
421 process.stdin.resume();
422 process.stdin.setEncoding('utf8');
423 process.stdin.on('data', function (param) {
424 process.stdin.pause();
425 pm2.delete(param, 'pipe');
426 });
427 } else
428 forEachLimit(name, 1, function(script, next) {
429 pm2.delete(script,'', next);
430 }, function(err) {
431 pm2.speedList(err ? 1 : 0);
432 });
433 });
434
435//
436// Send system signal to process
437//
438commander.command('sendSignal <signal> <pm2_id|name>')
439 .description('send a system signal to the target process')
440 .action(function(signal, pm2_id) {
441 if (isNaN(parseInt(pm2_id))) {
442 console.log(cst.PREFIX_MSG + 'Sending signal to process name ' + pm2_id);
443 pm2.sendSignalToProcessName(signal, pm2_id);
444 } else {
445 console.log(cst.PREFIX_MSG + 'Sending signal to process id ' + pm2_id);
446 pm2.sendSignalToProcessId(signal, pm2_id);
447 }
448 });
449
450//
451// Stop and delete a process by name from database
452//
453commander.command('ping')
454 .description('ping pm2 daemon - if not up it will launch it')
455 .action(function() {
456 pm2.ping();
457 });
458
459commander.command('updatePM2')
460 .description('update in-memory PM2 with local PM2')
461 .action(function() {
462 pm2.update();
463 });
464commander.command('update')
465 .description('(alias) update in-memory PM2 with local PM2')
466 .action(function() {
467 pm2.update();
468 });
469
470/**
471 * Module specifics
472 */
473commander.command('install <module|git:// url>')
474 .alias('module:install')
475 .option('--tarball', 'is local tarball')
476 .option('--http', 'is remote tarball')
477 .option('--docker', 'is docker container')
478 .option('--v1', 'install module in v1 manner (do not use it)')
479 .option('--safe [time]', 'keep module backup, if new module fail = restore with previous')
480 .description('install or update a module and run it forever')
481 .action(function(plugin_name, opts) {
482 require('util')._extend(commander, opts)
483 pm2.install(plugin_name, commander);
484 });
485
486commander.command('module:update <module|git:// url>')
487 .description('update a module and run it forever')
488 .action(function(plugin_name) {
489 pm2.install(plugin_name);
490 });
491
492
493commander.command('module:generate [app_name]')
494 .description('Generate a sample module in current folder')
495 .action(function(app_name) {
496 pm2.generateModuleSample(app_name);
497 });
498
499commander.command('uninstall <module>')
500 .alias('module:uninstall')
501 .description('stop and uninstall a module')
502 .action(function(plugin_name) {
503 pm2.uninstall(plugin_name);
504 });
505
506commander.command('package [target]')
507 .description('Check & Package TAR type module')
508 .action(function(target) {
509 pm2.package(target);
510 });
511
512commander.command('publish [folder]')
513 .option('--npm', 'publish on npm')
514 .alias('module:publish')
515 .description('Publish the module you are currently on')
516 .action(function(folder, opts) {
517 pm2.publish(folder, opts);
518 });
519
520commander.command('set [key] [value]')
521 .description('sets the specified config <key> <value>')
522 .action(function(key, value) {
523 pm2.set(key, value);
524 });
525
526commander.command('multiset <value>')
527 .description('multiset eg "key1 val1 key2 val2')
528 .action(function(str) {
529 pm2.multiset(str);
530 });
531
532commander.command('get [key]')
533 .description('get value for <key>')
534 .action(function(key) {
535 pm2.get(key);
536 });
537
538commander.command('conf [key] [value]')
539 .description('get / set module config values')
540 .action(function(key, value) {
541 pm2.conf(key, value);
542 });
543
544commander.command('config <key> [value]')
545 .description('get / set module config values')
546 .action(function(key, value) {
547 pm2.conf(key, value);
548 });
549
550commander.command('unset <key>')
551 .description('clears the specified config <key>')
552 .action(function(key) {
553 pm2.unset(key);
554 });
555
556commander.command('report')
557 .description('give a full pm2 report for https://github.com/Unitech/pm2/issues')
558 .action(function(key) {
559 pm2.report();
560 });
561
562//
563// PM2 I/O
564//
565commander.command('link [secret] [public] [name]')
566 .option('--info-node [url]', 'set url info node')
567 .option('--ws', 'websocket mode')
568 .option('--axon', 'axon mode')
569 .description('link with the pm2 monitoring dashboard')
570 .action(pm2.linkManagement.bind(pm2));
571
572commander.command('unlink')
573 .description('unlink with the pm2 monitoring dashboard')
574 .action(function() {
575 pm2.unlink();
576 });
577
578commander.command('monitor [name]')
579 .description('monitor target process')
580 .action(function(name) {
581 if (name === undefined) {
582 return plusHandler()
583 }
584 pm2.monitorState('monitor', name);
585 });
586
587commander.command('unmonitor [name]')
588 .description('unmonitor target process')
589 .action(function(name) {
590 pm2.monitorState('unmonitor', name);
591 });
592
593commander.command('open')
594 .description('open the pm2 monitoring dashboard')
595 .action(function(name) {
596 pm2.openDashboard();
597 });
598
599function plusHandler (command, opts) {
600 if (opts && opts.infoNode) {
601 process.env.KEYMETRICS_NODE = opts.infoNode
602 }
603
604 return PM2ioHandler.launch(command, opts)
605}
606
607commander.command('plus [command] [option]')
608 .alias('register')
609 .option('--info-node [url]', 'set url info node for on-premise pm2 plus')
610 .option('-d --discrete', 'silent mode')
611 .option('-a --install-all', 'install all modules (force yes)')
612 .description('enable pm2 plus')
613 .action(plusHandler);
614
615commander.command('login')
616 .description('Login to pm2 plus')
617 .action(function() {
618 return plusHandler('login')
619 });
620
621commander.command('logout')
622 .description('Logout from pm2 plus')
623 .action(function() {
624 return plusHandler('logout')
625 });
626
627//
628// Web interface
629//
630commander.command('web')
631 .description('launch a health API on ' + cst.WEB_IPADDR + ':' + cst.WEB_PORT)
632 .action(function() {
633 console.log('Launching web interface on ' + cst.WEB_IPADDR + ':' + cst.WEB_PORT);
634 pm2.web();
635 });
636
637//
638// Save processes to file
639//
640commander.command('dump')
641 .alias('save')
642 .description('dump all processes for resurrecting them later')
643 .action(failOnUnknown(function() {
644 pm2.dump();
645 }));
646
647//
648// Delete dump file
649//
650commander.command('cleardump')
651 .description('Create empty dump file')
652 .action(failOnUnknown(function() {
653 pm2.clearDump();
654 }));
655
656//
657// Save processes to file
658//
659commander.command('send <pm_id> <line>')
660 .description('send stdin to <pm_id>')
661 .action(function(pm_id, line) {
662 pm2.sendLineToStdin(pm_id, line);
663 });
664
665//
666// Attach to stdin/stdout
667// Not TTY ready
668//
669commander.command('attach <pm_id> [command separator]')
670 .description('attach stdin/stdout to application identified by <pm_id>')
671 .action(function(pm_id, separator) {
672 pm2.attach(pm_id, separator);
673 });
674
675//
676// Resurrect
677//
678commander.command('resurrect')
679 .description('resurrect previously dumped processes')
680 .action(failOnUnknown(function() {
681 console.log(cst.PREFIX_MSG + 'Resurrecting');
682 pm2.resurrect();
683 }));
684
685//
686// Set pm2 to startup
687//
688commander.command('unstartup [platform]')
689 .description('disable the pm2 startup hook')
690 .action(function(platform) {
691 pm2.uninstallStartup(platform, commander);
692 });
693
694//
695// Set pm2 to startup
696//
697commander.command('startup [platform]')
698 .description('enable the pm2 startup hook')
699 .action(function(platform) {
700 pm2.startup(platform, commander);
701 });
702
703//
704// Logrotate
705//
706commander.command('logrotate')
707 .description('copy default logrotate configuration')
708 .action(function(cmd) {
709 pm2.logrotate(commander);
710 });
711
712//
713// Sample generate
714//
715
716commander.command('ecosystem [mode]')
717 .alias('init')
718 .description('generate a process conf file. (mode = null or simple)')
719 .action(function(mode) {
720 pm2.generateSample(mode);
721 });
722
723commander.command('reset <name|id|all>')
724 .description('reset counters for process')
725 .action(function(proc_id) {
726 pm2.reset(proc_id);
727 });
728
729commander.command('describe <id>')
730 .description('describe all parameters of a process id')
731 .action(function(proc_id) {
732 pm2.describe(proc_id);
733 });
734
735commander.command('desc <id>')
736 .description('(alias) describe all parameters of a process id')
737 .action(function(proc_id) {
738 pm2.describe(proc_id);
739 });
740
741commander.command('info <id>')
742 .description('(alias) describe all parameters of a process id')
743 .action(function(proc_id) {
744 pm2.describe(proc_id);
745 });
746
747commander.command('env <id>')
748 .description('(alias) describe all parameters of a process id')
749 .action(function(proc_id) {
750 pm2.env(proc_id);
751 });
752
753commander.command('show <id>')
754 .description('(alias) describe all parameters of a process id')
755 .action(function(proc_id) {
756 pm2.describe(proc_id);
757 });
758
759//
760// List command
761//
762commander
763 .command('list')
764 .alias('ls')
765 .description('list all processes')
766 .action(function() {
767 pm2.list(commander)
768 });
769
770commander.command('l')
771 .description('(alias) list all processes')
772 .action(function() {
773 pm2.list()
774 });
775
776commander.command('ps')
777 .description('(alias) list all processes')
778 .action(function() {
779 pm2.list()
780 });
781
782commander.command('status')
783 .description('(alias) list all processes')
784 .action(function() {
785 pm2.list()
786 });
787
788
789// List in raw json
790commander.command('jlist')
791 .description('list all processes in JSON format')
792 .action(function() {
793 pm2.jlist()
794 });
795
796// List in prettified Json
797commander.command('prettylist')
798 .description('print json in a prettified JSON')
799 .action(failOnUnknown(function() {
800 pm2.jlist(true);
801 }));
802
803//
804// Dashboard command
805//
806commander.command('monit')
807 .description('launch termcaps monitoring')
808 .action(function() {
809 pm2.dashboard();
810 });
811
812commander.command('imonit')
813 .description('launch legacy termcaps monitoring')
814 .action(function() {
815 pm2.monit();
816 });
817
818commander.command('dashboard')
819 .alias('dash')
820 .description('launch dashboard with monitoring and logs')
821 .action(function() {
822 pm2.dashboard();
823 });
824
825
826//
827// Flushing command
828//
829
830commander.command('flush [api]')
831.description('flush logs')
832.action(function(api) {
833 pm2.flush(api);
834});
835
836/* old version
837commander.command('flush')
838 .description('flush logs')
839 .action(failOnUnknown(function() {
840 pm2.flush();
841 }));
842*/
843//
844// Reload all logs
845//
846commander.command('reloadLogs')
847 .description('reload all logs')
848 .action(function() {
849 pm2.reloadLogs();
850 });
851
852//
853// Log streaming
854//
855commander.command('logs [id|name]')
856 .option('--json', 'json log output')
857 .option('--format', 'formated log output')
858 .option('--raw', 'raw output')
859 .option('--err', 'only shows error output')
860 .option('--out', 'only shows standard output')
861 .option('--lines <n>', 'output the last N lines, instead of the last 15 by default')
862 .option('--timestamp [format]', 'add timestamps (default format YYYY-MM-DD-HH:mm:ss)')
863 .option('--nostream', 'print logs without lauching the log stream')
864 .description('stream logs file. Default stream all logs')
865 .action(function(id, cmd) {
866 var Logs = require('../lib/API/Log.js');
867
868 if (!id) id = 'all';
869
870 var line = 15;
871 var raw = false;
872 var exclusive = false;
873 var timestamp = false;
874
875 if(!isNaN(parseInt(cmd.lines))) {
876 line = parseInt(cmd.lines);
877 }
878
879 if (cmd.parent.rawArgs.indexOf('--raw') !== -1)
880 raw = true;
881
882 if (cmd.timestamp)
883 timestamp = typeof cmd.timestamp === 'string' ? cmd.timestamp : 'YYYY-MM-DD-HH:mm:ss';
884
885 if (cmd.out === true)
886 exclusive = 'out';
887
888 if (cmd.err === true)
889 exclusive = 'err';
890
891 if (cmd.nostream === true)
892 pm2.printLogs(id, line, raw, timestamp, exclusive);
893 else if (cmd.json === true)
894 Logs.jsonStream(pm2.Client, id);
895 else if (cmd.format === true)
896 Logs.formatStream(pm2.Client, id, false, 'YYYY-MM-DD-HH:mm:ssZZ');
897 else
898 pm2.streamLogs(id, line, raw, timestamp, exclusive);
899 });
900
901
902//
903// Kill
904//
905commander.command('kill')
906 .description('kill daemon')
907 .action(failOnUnknown(function(arg) {
908 pm2.killDaemon(function() {
909 process.exit(cst.SUCCESS_EXIT);
910 });
911 }));
912
913//
914// Update repository for a given app
915//
916
917commander.command('pull <name> [commit_id]')
918 .description('updates repository for a given app')
919 .action(function(pm2_name, commit_id) {
920
921 if (commit_id !== undefined) {
922 pm2._pullCommitId({
923 pm2_name: pm2_name,
924 commit_id: commit_id
925 });
926 }
927 else
928 pm2.pullAndRestart(pm2_name);
929 });
930
931//
932// Update repository to the next commit for a given app
933//
934commander.command('forward <name>')
935 .description('updates repository to the next commit for a given app')
936 .action(function(pm2_name) {
937 pm2.forward(pm2_name);
938 });
939
940//
941// Downgrade repository to the previous commit for a given app
942//
943commander.command('backward <name>')
944 .description('downgrades repository to the previous commit for a given app')
945 .action(function(pm2_name) {
946 pm2.backward(pm2_name);
947 });
948
949//
950// Perform a deep update of PM2
951//
952commander.command('deepUpdate')
953 .description('performs a deep update of PM2')
954 .action(function() {
955 pm2.deepUpdate();
956 });
957
958//
959// Launch a http server that expose a given path on given port
960//
961commander.command('serve [path] [port]')
962 .alias('expose')
963 .option('--port [port]', 'specify port to listen to')
964 .description('serve a directory over http via port')
965 .action(function (path, port, cmd) {
966 pm2.serve(path, port || cmd.port, commander);
967 });
968
969commander.command('examples')
970 .description('display pm2 usage examples')
971 .action(() => {
972 console.log(cst.PREFIX_MSG + chalk.grey('pm2 usage examples:\n'));
973 displayExamples();
974 process.exit(cst.SUCCESS_EXIT);
975 })
976
977//
978// Catch all
979//
980commander.command('*')
981 .action(function() {
982 console.log(cst.PREFIX_MSG + 'Command not found\n');
983 displayUsage();
984 // Check if it does not forget to close fds from RPC
985 process.exit(cst.ERROR_EXIT);
986 });
987
988//
989// Display help if 0 arguments passed to pm2
990//
991if (process.argv.length == 2) {
992 commander.parse(process.argv);
993 displayUsage();
994 // Check if it does not forget to close fds from RPC
995 process.exit(cst.ERROR_EXIT);
996}