@zappinginc/zm2 6.0.14

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