@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,775 @@
1
+
2
+ /***************************
3
+ *
4
+ * Extra methods
5
+ *
6
+ **************************/
7
+
8
+ var cst = require('../../constants.js');
9
+ var Common = require('../Common.js');
10
+ var UX = require('./UX');
11
+ var chalk = require('ansis');
12
+ var path = require('path');
13
+ var fs = require('fs');
14
+ var fmt = require('../tools/fmt.js');
15
+ var dayjs = require('dayjs');
16
+ var pkg = require('../../package.json');
17
+ const copyDirSync = require('../tools/copydirSync.js')
18
+
19
+ module.exports = function(CLI) {
20
+ /**
21
+ * Get version of the daemonized PM2
22
+ * @method getVersion
23
+ * @callback cb
24
+ */
25
+ CLI.prototype.getVersion = function(cb) {
26
+ var that = this;
27
+
28
+ that.Client.executeRemote('getVersion', {}, function(err) {
29
+ return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
30
+ });
31
+ };
32
+
33
+ /**
34
+ * Install pm2-sysmonit
35
+ */
36
+ CLI.prototype.launchSysMonitoring = function(cb) {
37
+ if ((this.pm2_configuration && this.pm2_configuration.sysmonit != 'true') ||
38
+ process.env.TRAVIS ||
39
+ global.it === 'function' ||
40
+ cst.IS_WINDOWS === true)
41
+ return cb ? cb(null) : null
42
+
43
+ var filepath
44
+
45
+ try {
46
+ filepath = path.dirname(require.resolve('pm2-sysmonit'))
47
+ } catch(e) {
48
+ return cb ? cb(null) : null
49
+ }
50
+
51
+ this.start({
52
+ script: filepath
53
+ }, {
54
+ started_as_module : true
55
+ }, (err, res) => {
56
+ if (err) {
57
+ Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
58
+ return cb ? cb(err) : this.speedList(cst.ERROR_EXIT);
59
+ }
60
+ return cb ? cb(null) : this.speedList();
61
+ });
62
+ };
63
+
64
+ /**
65
+ * Show application environment
66
+ * @method env
67
+ * @callback cb
68
+ */
69
+ CLI.prototype.env = function(app_id, cb) {
70
+ var procs = []
71
+ var printed = 0
72
+
73
+ this.Client.executeRemote('getMonitorData', {}, (err, list) => {
74
+ list.forEach(l => {
75
+ if (app_id == l.pm_id) {
76
+ printed++
77
+ var env = Common.safeExtend({}, l.pm2_env)
78
+ Object.keys(env).forEach(key => {
79
+ console.log(`${key}: ${chalk.green(env[key])}`)
80
+ })
81
+ }
82
+ })
83
+
84
+ if (printed == 0) {
85
+ Common.err(`Modules with id ${app_id} not found`)
86
+ return cb ? cb.apply(null, arguments) : this.exitCli(cst.ERROR_EXIT);
87
+ }
88
+ return cb ? cb.apply(null, arguments) : this.exitCli(cst.SUCCESS_EXIT);
89
+ })
90
+ };
91
+
92
+ /**
93
+ * Get version of the daemonized PM2
94
+ * @method getVersion
95
+ * @callback cb
96
+ */
97
+ CLI.prototype.report = function() {
98
+ var that = this;
99
+
100
+ var Log = require('./Log');
101
+
102
+ that.Client.executeRemote('getReport', {}, function(err, report) {
103
+
104
+ console.log()
105
+ console.log()
106
+ console.log()
107
+ console.log('```')
108
+ fmt.title('PM2 report')
109
+ fmt.field('Date', new Date());
110
+ fmt.sep();
111
+
112
+ if (report && !err) {
113
+ fmt.title(chalk.bold.blue('Daemon'));
114
+ fmt.field('pm2d version', report.pm2_version);
115
+ fmt.field('node version', report.node_version);
116
+ fmt.field('node path', report.node_path);
117
+ fmt.field('argv', report.argv);
118
+ fmt.field('argv0', report.argv0);
119
+ fmt.field('user', report.user);
120
+ fmt.field('uid', report.uid);
121
+ fmt.field('gid', report.gid);
122
+ fmt.field('uptime', dayjs(new Date()).diff(report.started_at, 'minute') + 'min');
123
+ }
124
+
125
+ fmt.sep();
126
+ fmt.title(chalk.bold.blue('CLI'));
127
+ fmt.field('local pm2', pkg.version);
128
+ fmt.field('node version', process.versions.node);
129
+ fmt.field('node path', process.env['_'] || 'not found');
130
+ fmt.field('argv', process.argv);
131
+ fmt.field('argv0', process.argv0);
132
+ fmt.field('user', process.env.USER || process.env.LNAME || process.env.USERNAME);
133
+ if (cst.IS_WINDOWS === false && process.geteuid)
134
+ fmt.field('uid', process.geteuid());
135
+ if (cst.IS_WINDOWS === false && process.getegid)
136
+ fmt.field('gid', process.getegid());
137
+
138
+ var os = require('os');
139
+
140
+ fmt.sep();
141
+ fmt.title(chalk.bold.blue('System info'));
142
+ fmt.field('arch', os.arch());
143
+ fmt.field('platform', os.platform());
144
+ fmt.field('type', os.type());
145
+ fmt.field('cpus', os.cpus()[0].model);
146
+ fmt.field('cpus nb', Object.keys(os.cpus()).length);
147
+ fmt.field('freemem', os.freemem());
148
+ fmt.field('totalmem', os.totalmem());
149
+ fmt.field('home', os.homedir());
150
+
151
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
152
+
153
+ fmt.sep();
154
+ fmt.title(chalk.bold.blue('PM2 list'));
155
+ UX.list(list, that.gl_interact_infos);
156
+
157
+ fmt.sep();
158
+ fmt.title(chalk.bold.blue('Daemon logs'));
159
+ Log.tail([{
160
+ path : cst.PM2_LOG_FILE_PATH,
161
+ app_name : 'PM2',
162
+ type : 'PM2'
163
+ }], 20, false, function() {
164
+ console.log('```')
165
+ console.log()
166
+ console.log()
167
+
168
+ console.log(chalk.bold.green('Please copy/paste the above report in your issue on https://github.com/Unitech/pm2/issues'));
169
+
170
+ console.log()
171
+ console.log()
172
+ that.exitCli(cst.SUCCESS_EXIT);
173
+ });
174
+ });
175
+ });
176
+ };
177
+
178
+ CLI.prototype.getPID = function(app_name, cb) {
179
+ var that = this;
180
+
181
+ if (typeof(app_name) === 'function') {
182
+ cb = app_name;
183
+ app_name = null;
184
+ }
185
+
186
+ this.Client.executeRemote('getMonitorData', {}, function(err, list) {
187
+ if (err) {
188
+ Common.printError(cst.PREFIX_MSG_ERR + err);
189
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
190
+ }
191
+
192
+ var pids = [];
193
+
194
+ list.forEach(function(app) {
195
+ if (!app_name || app_name == app.name)
196
+ pids.push(app.pid);
197
+ })
198
+
199
+ if (!cb) {
200
+ Common.printOut(pids.join("\n"))
201
+ return that.exitCli(cst.SUCCESS_EXIT);
202
+ }
203
+ return cb(null, pids);
204
+ })
205
+ }
206
+
207
+ /**
208
+ * Create PM2 memory snapshot
209
+ * @method getVersion
210
+ * @callback cb
211
+ */
212
+ CLI.prototype.profile = function(type, time, cb) {
213
+ var that = this;
214
+ var dayjs = require('dayjs');
215
+ var cmd
216
+
217
+ if (type == 'cpu') {
218
+ cmd = {
219
+ ext: '.cpuprofile',
220
+ action: 'profileCPU'
221
+ }
222
+ }
223
+ if (type == 'mem') {
224
+ cmd = {
225
+ ext: '.heapprofile',
226
+ action: 'profileMEM'
227
+ }
228
+ }
229
+
230
+ var file = path.join(process.cwd(), dayjs().format('dd-HH:mm:ss') + cmd.ext);
231
+ time = time || 10000
232
+
233
+ console.log(`Starting ${cmd.action} profiling for ${time}ms...`)
234
+ that.Client.executeRemote(cmd.action, {
235
+ pwd : file,
236
+ timeout: time
237
+ }, function(err) {
238
+ if (err) {
239
+ console.error(err);
240
+ return that.exitCli(1);
241
+ }
242
+ console.log(`Profile done in ${file}`)
243
+ return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
244
+ });
245
+ };
246
+
247
+
248
+ function basicMDHighlight(lines) {
249
+ console.log('\n\n+-------------------------------------+')
250
+ console.log(chalk.bold('README.md content:'))
251
+ lines = lines.split('\n')
252
+ var isInner = false
253
+ lines.forEach(l => {
254
+ if (l.startsWith('#'))
255
+ console.log(chalk.bold.green(l))
256
+ else if (isInner || l.startsWith('```')) {
257
+ if (isInner && l.startsWith('```'))
258
+ isInner = false
259
+ else if (isInner == false)
260
+ isInner = true
261
+ console.log(chalk.gray(l))
262
+ }
263
+ else if (l.startsWith('`'))
264
+ console.log(chalk.gray(l))
265
+ else
266
+ console.log(l)
267
+ })
268
+ console.log('+-------------------------------------+')
269
+ }
270
+ /**
271
+ * pm2 create command
272
+ * create boilerplate of application for fast try
273
+ * @method boilerplate
274
+ */
275
+ CLI.prototype.boilerplate = function(cb) {
276
+ var i = 0
277
+ var projects = []
278
+ var enquirer = require('enquirer')
279
+ const forEach = require('async/forEach')
280
+
281
+ fs.readdir(path.join(__dirname, '../templates/sample-apps'), (err, items) => {
282
+ forEach(items, (app, next) => {
283
+ var fp = path.join(__dirname, '../templates/sample-apps', app)
284
+ fs.readFile(path.join(fp, 'package.json'), (err, dt) => {
285
+ var meta = JSON.parse(dt)
286
+ meta.fullpath = fp
287
+ meta.folder_name = app
288
+ projects.push(meta)
289
+ next()
290
+ })
291
+ }, () => {
292
+ const prompt = new enquirer.Select({
293
+ name: 'boilerplate',
294
+ message: 'Select a boilerplate',
295
+ choices: projects.map((p, i) => {
296
+ return {
297
+ message: `${chalk.bold.blue(p.name)} ${p.description}`,
298
+ value: `${i}`
299
+ }
300
+ })
301
+ });
302
+
303
+ prompt.run()
304
+ .then(answer => {
305
+ var p = projects[parseInt(answer)]
306
+ basicMDHighlight(fs.readFileSync(path.join(p.fullpath, 'README.md')).toString())
307
+ console.log(chalk.bold(`>> Project copied inside folder ./${p.folder_name}/\n`))
308
+ copyDirSync(p.fullpath, path.join(process.cwd(), p.folder_name));
309
+ this.start(path.join(p.fullpath, 'ecosystem.config.js'), {
310
+ cwd: p.fullpath
311
+ }, () => {
312
+ return cb ? cb.apply(null, arguments) : this.speedList(cst.SUCCESS_EXIT);
313
+ })
314
+ })
315
+ .catch(e => {
316
+ return cb ? cb.apply(null, arguments) : this.speedList(cst.SUCCESS_EXIT);
317
+ });
318
+
319
+ })
320
+ })
321
+ }
322
+
323
+ /**
324
+ * Description
325
+ * @method sendLineToStdin
326
+ */
327
+ CLI.prototype.sendLineToStdin = function(pm_id, line, separator, cb) {
328
+ var that = this;
329
+
330
+ if (!cb && typeof(separator) == 'function') {
331
+ cb = separator;
332
+ separator = null;
333
+ }
334
+
335
+ var packet = {
336
+ pm_id : pm_id,
337
+ line : line + (separator || '\n')
338
+ };
339
+
340
+ that.Client.executeRemote('sendLineToStdin', packet, function(err, res) {
341
+ if (err) {
342
+ Common.printError(cst.PREFIX_MSG_ERR + err);
343
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
344
+ }
345
+ return cb ? cb(null, res) : that.speedList();
346
+ });
347
+ };
348
+
349
+ /**
350
+ * Description
351
+ * @method attachToProcess
352
+ */
353
+ CLI.prototype.attach = function(pm_id, separator, cb) {
354
+ var that = this;
355
+ var readline = require('readline');
356
+
357
+ if (isNaN(pm_id)) {
358
+ Common.printError('pm_id must be a process number (not a process name)');
359
+ return cb ? cb(Common.retErr('pm_id must be number')) : that.exitCli(cst.ERROR_EXIT);
360
+ }
361
+
362
+ if (typeof(separator) == 'function') {
363
+ cb = separator;
364
+ separator = null;
365
+ }
366
+
367
+ var rl = readline.createInterface({
368
+ input: process.stdin,
369
+ output: process.stdout
370
+ });
371
+
372
+ rl.on('close', function() {
373
+ return cb ? cb() : that.exitCli(cst.SUCCESS_EXIT);
374
+ });
375
+
376
+ that.Client.launchBus(function(err, bus, socket) {
377
+ if (err) {
378
+ Common.printError(err);
379
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
380
+ }
381
+
382
+ bus.on('log:*', function(type, packet) {
383
+ if (packet.process.pm_id !== parseInt(pm_id))
384
+ return;
385
+ process.stdout.write(packet.data);
386
+ });
387
+ });
388
+
389
+ rl.on('line', function(line) {
390
+ that.sendLineToStdin(pm_id, line, separator, function() {});
391
+ });
392
+ };
393
+
394
+ /**
395
+ * Description
396
+ * @method sendDataToProcessId
397
+ */
398
+ CLI.prototype.sendDataToProcessId = function(proc_id, packet, cb) {
399
+ var that = this;
400
+
401
+ if (typeof proc_id === 'object' && typeof packet === 'function') {
402
+ // the proc_id is packet.
403
+ cb = packet;
404
+ packet = proc_id;
405
+ } else {
406
+ packet.id = proc_id;
407
+ }
408
+
409
+ that.Client.executeRemote('sendDataToProcessId', packet, function(err, res) {
410
+ if (err) {
411
+ Common.printError(err);
412
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
413
+ }
414
+ Common.printOut('successfully sent data to process');
415
+ return cb ? cb(null, res) : that.speedList();
416
+ });
417
+ };
418
+
419
+ /**
420
+ * Used for custom actions, allows to trigger function inside an app
421
+ * To expose a function you need to use keymetrics/pmx
422
+ *
423
+ * @method msgProcess
424
+ * @param {Object} opts
425
+ * @param {String} id process id
426
+ * @param {String} action_name function name to trigger
427
+ * @param {Object} [opts.opts] object passed as first arg of the function
428
+ * @param {String} [uuid] optional unique identifier when logs are emitted
429
+ *
430
+ */
431
+ CLI.prototype.msgProcess = function(opts, cb) {
432
+ var that = this;
433
+
434
+ that.Client.executeRemote('msgProcess', opts, cb);
435
+ };
436
+
437
+ /**
438
+ * Trigger a PMX custom action in target application
439
+ * Custom actions allows to interact with an application
440
+ *
441
+ * @method trigger
442
+ * @param {String|Number} pm_id process id or application name
443
+ * @param {String} action_name name of the custom action to trigger
444
+ * @param {Mixed} params parameter to pass to target action
445
+ * @param {Function} cb callback
446
+ */
447
+ CLI.prototype.trigger = function(pm_id, action_name, params, cb) {
448
+ if (typeof(params) === 'function') {
449
+ cb = params;
450
+ params = null;
451
+ }
452
+ var cmd = {
453
+ msg : action_name
454
+ };
455
+ var counter = 0;
456
+ var process_wait_count = 0;
457
+ var that = this;
458
+ var results = [];
459
+
460
+ if (params)
461
+ cmd.opts = params;
462
+ if (isNaN(pm_id))
463
+ cmd.name = pm_id;
464
+ else
465
+ cmd.id = pm_id;
466
+
467
+ this.launchBus(function(err, bus) {
468
+ bus.on('axm:reply', function(ret) {
469
+ if (ret.process.name == pm_id || ret.process.pm_id == pm_id || ret.process.namespace == pm_id || pm_id == 'all') {
470
+ results.push(ret);
471
+ Common.printOut('[%s:%s:%s]=%j', ret.process.name, ret.process.pm_id, ret.process.namespace, ret.data.return);
472
+ if (++counter == process_wait_count)
473
+ return cb ? cb(null, results) : that.exitCli(cst.SUCCESS_EXIT);
474
+ }
475
+ });
476
+
477
+ that.msgProcess(cmd, function(err, data) {
478
+ if (err) {
479
+ Common.printError(err);
480
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
481
+ }
482
+
483
+ if (data.process_count == 0) {
484
+ Common.printError('Not any process has received a command (offline or unexistent)');
485
+ return cb ? cb(Common.retErr('Unknown process')) : that.exitCli(cst.ERROR_EXIT);
486
+ }
487
+
488
+ process_wait_count = data.process_count;
489
+ Common.printOut(chalk.bold('%s processes have received command %s'),
490
+ data.process_count, action_name);
491
+ });
492
+ });
493
+ };
494
+
495
+ /**
496
+ * Description
497
+ * @method sendSignalToProcessName
498
+ * @param {} signal
499
+ * @param {} process_name
500
+ * @return
501
+ */
502
+ CLI.prototype.sendSignalToProcessName = function(signal, process_name, cb) {
503
+ var that = this;
504
+
505
+ that.Client.executeRemote('sendSignalToProcessName', {
506
+ signal : signal,
507
+ process_name : process_name
508
+ }, function(err, list) {
509
+ if (err) {
510
+ Common.printError(err);
511
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
512
+ }
513
+ Common.printOut('successfully sent signal %s to process name %s', signal, process_name);
514
+ return cb ? cb(null, list) : that.speedList();
515
+ });
516
+ };
517
+
518
+ /**
519
+ * Description
520
+ * @method sendSignalToProcessId
521
+ * @param {} signal
522
+ * @param {} process_id
523
+ * @return
524
+ */
525
+ CLI.prototype.sendSignalToProcessId = function(signal, process_id, cb) {
526
+ var that = this;
527
+
528
+ that.Client.executeRemote('sendSignalToProcessId', {
529
+ signal : signal,
530
+ process_id : process_id
531
+ }, function(err, list) {
532
+ if (err) {
533
+ Common.printError(err);
534
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
535
+ }
536
+ Common.printOut('successfully sent signal %s to process id %s', signal, process_id);
537
+ return cb ? cb(null, list) : that.speedList();
538
+ });
539
+ };
540
+
541
+ /**
542
+ * API method to launch a process that will serve directory over http
543
+ */
544
+ CLI.prototype.autoinstall = function (cb) {
545
+ var filepath = path.resolve(path.dirname(module.filename), '../Sysinfo/ServiceDetection/ServiceDetection.js');
546
+
547
+ this.start(filepath, (err, res) => {
548
+ if (err) {
549
+ Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
550
+ return cb ? cb(err) : this.speedList(cst.ERROR_EXIT);
551
+ }
552
+ return cb ? cb(null) : this.speedList();
553
+ });
554
+ }
555
+
556
+ /**
557
+ * API method to launch a process that will serve directory over http
558
+ *
559
+ * @param {Object} opts options
560
+ * @param {String} opts.path path to be served
561
+ * @param {Number} opts.port port on which http will bind
562
+ * @param {Boolean} opts.spa single page app served
563
+ * @param {String} opts.basicAuthUsername basic auth username
564
+ * @param {String} opts.basicAuthPassword basic auth password
565
+ * @param {Object} commander commander object
566
+ * @param {Function} cb optional callback
567
+ */
568
+ CLI.prototype.serve = function (target_path, port, opts, commander, cb) {
569
+ var that = this;
570
+ var servePort = process.env.PM2_SERVE_PORT || port || 8080;
571
+ var servePath = path.resolve(process.env.PM2_SERVE_PATH || target_path || '.');
572
+
573
+ var filepath = path.resolve(path.dirname(module.filename), './Serve.js');
574
+
575
+ if (typeof commander.name === 'string')
576
+ opts.name = commander.name
577
+ else
578
+ opts.name = 'static-page-server-' + servePort
579
+ if (!opts.env)
580
+ opts.env = {};
581
+ opts.env.PM2_SERVE_PORT = servePort;
582
+ opts.env.PM2_SERVE_PATH = servePath;
583
+ opts.env.PM2_SERVE_SPA = opts.spa;
584
+ if (opts.basicAuthUsername && opts.basicAuthPassword) {
585
+ opts.env.PM2_SERVE_BASIC_AUTH = 'true';
586
+ opts.env.PM2_SERVE_BASIC_AUTH_USERNAME = opts.basicAuthUsername;
587
+ opts.env.PM2_SERVE_BASIC_AUTH_PASSWORD = opts.basicAuthPassword;
588
+ }
589
+ if (opts.monitor) {
590
+ opts.env.PM2_SERVE_MONITOR = opts.monitor
591
+ }
592
+ opts.cwd = servePath;
593
+
594
+ this.start(filepath, opts, function (err, res) {
595
+ if (err) {
596
+ Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
597
+ return cb ? cb(err) : that.speedList(cst.ERROR_EXIT);
598
+ }
599
+ Common.printOut(cst.PREFIX_MSG + 'Serving ' + servePath + ' on port ' + servePort);
600
+ return cb ? cb(null, res) : that.speedList();
601
+ });
602
+ }
603
+
604
+ /**
605
+ * Ping daemon - if PM2 daemon not launched, it will launch it
606
+ * @method ping
607
+ */
608
+ CLI.prototype.ping = function(cb) {
609
+ var that = this;
610
+
611
+ that.Client.executeRemote('ping', {}, function(err, res) {
612
+ if (err) {
613
+ Common.printError(err);
614
+ return cb ? cb(new Error(err)) : that.exitCli(cst.ERROR_EXIT);
615
+ }
616
+ Common.printOut(res);
617
+ return cb ? cb(null, res) : that.exitCli(cst.SUCCESS_EXIT);
618
+ });
619
+ };
620
+
621
+
622
+ /**
623
+ * Execute remote command
624
+ */
625
+ CLI.prototype.remote = function(command, opts, cb) {
626
+ var that = this;
627
+
628
+ that[command](opts.name, function(err_cmd, ret) {
629
+ if (err_cmd)
630
+ console.error(err_cmd);
631
+ console.log('Command %s finished', command);
632
+ return cb(err_cmd, ret);
633
+ });
634
+ };
635
+
636
+ /**
637
+ * This remote method allows to pass multiple arguments
638
+ * to PM2
639
+ * It is used for the new scoped PM2 action system
640
+ */
641
+ CLI.prototype.remoteV2 = function(command, opts, cb) {
642
+ var that = this;
643
+
644
+ if (that[command].length == 1)
645
+ return that[command](cb);
646
+
647
+ opts.args.push(cb);
648
+ return that[command].apply(this, opts.args);
649
+ };
650
+
651
+
652
+ /**
653
+ * Description
654
+ * @method generateSample
655
+ * @param {} name
656
+ * @return
657
+ */
658
+ CLI.prototype.generateSample = function(mode) {
659
+ var that = this;
660
+ var templatePath;
661
+
662
+ if (mode == 'simple')
663
+ templatePath = path.join(cst.TEMPLATE_FOLDER, cst.APP_CONF_TPL_SIMPLE);
664
+ else
665
+ templatePath = path.join(cst.TEMPLATE_FOLDER, cst.APP_CONF_TPL);
666
+
667
+ var sample = fs.readFileSync(templatePath);
668
+ var dt = sample.toString();
669
+ var f_name = 'ecosystem.config.js';
670
+ var pwd = process.env.PWD || process.cwd();
671
+
672
+ try {
673
+ fs.writeFileSync(path.join(pwd, f_name), dt);
674
+ } catch (e) {
675
+ console.error(e.stack || e);
676
+ return that.exitCli(cst.ERROR_EXIT);
677
+ }
678
+ Common.printOut('File %s generated', path.join(pwd, f_name));
679
+ that.exitCli(cst.SUCCESS_EXIT);
680
+ };
681
+
682
+ /**
683
+ * Description
684
+ * @method dashboard
685
+ * @return
686
+ */
687
+ CLI.prototype.dashboard = function(cb) {
688
+ var that = this;
689
+
690
+ var Dashboard = require('./Dashboard');
691
+
692
+ if (cb)
693
+ return cb(new Error('Dashboard cant be called programmatically'));
694
+
695
+ Dashboard.init();
696
+
697
+ this.Client.launchBus(function (err, bus) {
698
+ if (err) {
699
+ console.error('Error launchBus: ' + err);
700
+ that.exitCli(cst.ERROR_EXIT);
701
+ }
702
+ bus.on('log:*', function(type, data) {
703
+ Dashboard.log(type, data)
704
+ })
705
+ });
706
+
707
+ process.on('SIGINT', function() {
708
+ this.Client.disconnectBus(function() {
709
+ process.exit(cst.SUCCESS_EXIT);
710
+ });
711
+ });
712
+
713
+ function refreshDashboard() {
714
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
715
+ if (err) {
716
+ console.error('Error retrieving process list: ' + err);
717
+ that.exitCli(cst.ERROR_EXIT);
718
+ }
719
+
720
+ Dashboard.refresh(list);
721
+
722
+ setTimeout(function() {
723
+ refreshDashboard();
724
+ }, 800);
725
+ });
726
+ }
727
+
728
+ refreshDashboard();
729
+ };
730
+
731
+ CLI.prototype.monit = function(cb) {
732
+ var that = this;
733
+
734
+ var Monit = require('./Monit.js');
735
+
736
+ if (cb) return cb(new Error('Monit cant be called programmatically'));
737
+
738
+ Monit.init();
739
+
740
+ function launchMonitor() {
741
+ that.Client.executeRemote('getMonitorData', {}, function(err, list) {
742
+ if (err) {
743
+ console.error('Error retrieving process list: ' + err);
744
+ that.exitCli(conf.ERROR_EXIT);
745
+ }
746
+
747
+ Monit.refresh(list);
748
+
749
+ setTimeout(function() {
750
+ launchMonitor();
751
+ }, 400);
752
+ });
753
+ }
754
+
755
+ launchMonitor();
756
+ };
757
+
758
+ CLI.prototype.inspect = function(app_name, cb) {
759
+ const that = this;
760
+ this.trigger(app_name, 'internal:inspect', function (err, res) {
761
+
762
+ if(res && res[0]) {
763
+ if (res[0].data.return === '') {
764
+ Common.printOut(`Inspect disabled on ${app_name}`);
765
+ } else {
766
+ Common.printOut(`Inspect enabled on ${app_name} => go to chrome : chrome://inspect !!!`);
767
+ }
768
+ } else {
769
+ Common.printOut(`Unable to activate inspect mode on ${app_name} !!!`);
770
+ }
771
+
772
+ that.exitCli(cst.SUCCESS_EXIT);
773
+ });
774
+ };
775
+ };