UNPKG

25.4 kBJavaScriptView Raw
1/**
2 * Copyright 2013-2021 the PM2 project authors. All rights reserved.
3 * Use of this source code is governed by a license that
4 * can be found in the LICENSE file.
5 */
6'use strict';
7
8/**
9 * @file ActionMethod like restart, stop, monitor... are here
10 * @author Alexandre Strzelewicz <as@unitech.io>
11 * @project PM2
12 */
13
14var fs = require('fs');
15var path = require('path');
16var eachLimit = require('async/eachLimit');
17var os = require('os');
18var p = path;
19var cst = require('../../constants.js');
20var pkg = require('../../package.json');
21var pidusage = require('pidusage');
22var util = require('util');
23var debug = require('debug')('pm2:ActionMethod');
24var Utility = require('../Utility');
25
26/**
27 * Description
28 * @method exports
29 * @param {} God
30 * @return
31 */
32module.exports = function(God) {
33 /**
34 * Description
35 * @method getMonitorData
36 * @param {} env
37 * @param {} cb
38 * @return
39 */
40 God.getMonitorData = function getMonitorData(env, cb) {
41 var processes = God.getFormatedProcesses();
42 var pids = processes.filter(filterBadProcess)
43 .map(function(pro, i) {
44 var pid = getProcessId(pro)
45 return pid;
46 })
47
48 // No pids, return empty statistics
49 if (pids.length === 0) {
50 return cb(null, processes.map(function(pro) {
51 pro['monit'] = {
52 memory : 0,
53 cpu : 0
54 };
55
56 return pro
57 }))
58 }
59
60 pidusage(pids, function retPidUsage(err, statistics) {
61 // Just log, we'll set empty statistics
62 if (err) {
63 console.error('Error caught while calling pidusage');
64 console.error(err);
65
66 return cb(null, processes.map(function(pro) {
67 pro['monit'] = {
68 memory : 0,
69 cpu : 0
70 };
71 return pro
72 }))
73 }
74
75 if (!statistics) {
76 console.error('Statistics is not defined!')
77
78 return cb(null, processes.map(function(pro) {
79 pro['monit'] = {
80 memory : 0,
81 cpu : 0
82 };
83 return pro
84 }))
85 }
86
87 processes = processes.map(function(pro) {
88 if (filterBadProcess(pro) === false) {
89 pro['monit'] = {
90 memory : 0,
91 cpu : 0
92 };
93
94 return pro;
95 }
96
97 var pid = getProcessId(pro);
98 var stat = statistics[pid];
99
100 if (!stat) {
101 pro['monit'] = {
102 memory : 0,
103 cpu : 0
104 };
105
106 return pro;
107 }
108
109 pro['monit'] = {
110 memory: stat.memory,
111 cpu: Math.round(stat.cpu * 10) / 10
112 };
113
114 return pro;
115 });
116
117 cb(null, processes);
118 });
119 };
120
121 /**
122 * Description
123 * @method getSystemData
124 * @param {} env
125 * @param {} cb
126 * @return
127 */
128 God.getSystemData = function getSystemData(env, cb) {
129 if (God.system_infos_proc !== null)
130 God.system_infos_proc.query((err, data) => {
131 cb(null, data)
132 })
133 else {
134 cb(new Error('Sysinfos not launched, type: pm2 sysmonit'))
135 }
136 };
137
138 /**
139 * Description
140 * @method dumpProcessList
141 * @param {} cb
142 * @return
143 */
144 God.dumpProcessList = function(cb) {
145 var process_list = [];
146 var apps = Utility.clone(God.getFormatedProcesses());
147 var that = this;
148
149 // Don't override the actual dump file if process list is empty
150 // unless user explicitely did `pm2 dump`.
151 // This often happens when PM2 crashed, we don't want to override
152 // the dump file with an empty list of process.
153 if (!apps[0]) {
154 debug('[PM2] Did not override dump file because list of processes is empty');
155 return cb(null, {success:true, process_list: process_list});
156 }
157
158 function fin(err) {
159
160 // try to fix issues with empty dump file
161 // like #3485
162 if (process_list.length === 0) {
163
164 // fix : if no dump file, no process, only module and after pm2 update
165 if (!fs.existsSync(cst.DUMP_FILE_PATH) && typeof that.clearDump === 'function') {
166 that.clearDump(function(){});
167 }
168
169 // if no process in list don't modify dump file
170 // process list should not be empty
171 return cb(null, {success:true, process_list: process_list});
172 }
173
174 // Back up dump file
175 try {
176 if (fs.existsSync(cst.DUMP_FILE_PATH)) {
177 fs.writeFileSync(cst.DUMP_BACKUP_FILE_PATH, fs.readFileSync(cst.DUMP_FILE_PATH));
178 }
179 } catch (e) {
180 console.error(e.stack || e);
181 }
182
183 // Overwrite dump file, delete if broken
184 try {
185 fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify(process_list));
186 } catch (e) {
187 console.error(e.stack || e);
188 try {
189 // try to backup file
190 if (fs.existsSync(cst.DUMP_BACKUP_FILE_PATH)) {
191 fs.writeFileSync(cst.DUMP_FILE_PATH, fs.readFileSync(cst.DUMP_BACKUP_FILE_PATH));
192 }
193 } catch (e) {
194 // don't keep broken file
195 fs.unlinkSync(cst.DUMP_FILE_PATH);
196 console.error(e.stack || e);
197 }
198 }
199
200 return cb(null, {success:true, process_list: process_list});
201 }
202
203 function saveProc(apps) {
204 if (!apps[0])
205 return fin(null);
206 delete apps[0].pm2_env.instances;
207 delete apps[0].pm2_env.pm_id;
208 // Do not dump modules
209 if (!apps[0].pm2_env.pmx_module)
210 process_list.push(apps[0].pm2_env);
211 apps.shift();
212 return saveProc(apps);
213 }
214 saveProc(apps);
215 };
216
217 /**
218 * Description
219 * @method ping
220 * @param {} env
221 * @param {} cb
222 * @return CallExpression
223 */
224 God.ping = function(env, cb) {
225 return cb(null, {msg : 'pong'});
226 };
227
228 /**
229 * Description
230 * @method notifyKillPM2
231 */
232 God.notifyKillPM2 = function() {
233 God.pm2_being_killed = true;
234 };
235
236 /**
237 * Duplicate a process
238 * @method duplicateProcessId
239 * @param {} id
240 * @param {} cb
241 * @return CallExpression
242 */
243 God.duplicateProcessId = function(id, cb) {
244 if (!(id in God.clusters_db))
245 return cb(God.logAndGenerateError(id + ' id unknown'), {});
246
247 if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env)
248 return cb(God.logAndGenerateError('Error when getting proc || proc.pm2_env'), {});
249
250 var proc = Utility.clone(God.clusters_db[id].pm2_env);
251
252
253 delete proc.created_at;
254 delete proc.pm_id;
255 delete proc.unique_id;
256
257 // generate a new unique id for new process
258 proc.unique_id = Utility.generateUUID()
259
260 God.injectVariables(proc, function inject (_err, proc) {
261 return God.executeApp(Utility.clone(proc), function (err, clu) {
262 if (err) return cb(err);
263 God.notify('start', clu, true);
264 return cb(err, Utility.clone(clu));
265 });
266 });
267 };
268
269 /**
270 * Start a stopped process by ID
271 * @method startProcessId
272 * @param {} id
273 * @param {} cb
274 * @return CallExpression
275 */
276 God.startProcessId = function(id, cb) {
277 if (!(id in God.clusters_db))
278 return cb(God.logAndGenerateError(id + ' id unknown'), {});
279
280 var proc = God.clusters_db[id];
281 if (proc.pm2_env.status == cst.ONLINE_STATUS)
282 return cb(God.logAndGenerateError('process already online'), {});
283 if (proc.pm2_env.status == cst.LAUNCHING_STATUS)
284 return cb(God.logAndGenerateError('process already started'), {});
285 if (proc.process && proc.process.pid)
286 return cb(God.logAndGenerateError('Process with pid ' + proc.process.pid + ' already exists'), {});
287
288 return God.executeApp(God.clusters_db[id].pm2_env, function(err, proc) {
289 return cb(err, Utility.clone(proc));
290 });
291 };
292
293
294 /**
295 * Stop a process and set it on state 'stopped'
296 * @method stopProcessId
297 * @param {} id
298 * @param {} cb
299 * @return Literal
300 */
301 God.stopProcessId = function(id, cb) {
302 if (typeof id == 'object' && 'id' in id)
303 id = id.id;
304
305 if (!(id in God.clusters_db))
306 return cb(God.logAndGenerateError(id + ' : id unknown'), {});
307
308 var proc = God.clusters_db[id];
309
310 //clear time-out restart task
311 clearTimeout(proc.pm2_env.restart_task);
312
313 if (proc.pm2_env.status == cst.STOPPED_STATUS) {
314 proc.process.pid = 0;
315 return cb(null, God.getFormatedProcess(id));
316 }
317 // state == 'none' means that the process is not online yet
318 if (proc.state && proc.state === 'none')
319 return setTimeout(function() { God.stopProcessId(id, cb); }, 250);
320
321 console.log('Stopping app:%s id:%s', proc.pm2_env.name, proc.pm2_env.pm_id);
322 proc.pm2_env.status = cst.STOPPING_STATUS;
323
324 if (!proc.process.pid) {
325 console.error('app=%s id=%d does not have a pid', proc.pm2_env.name, proc.pm2_env.pm_id);
326 proc.pm2_env.status = cst.STOPPED_STATUS;
327 return cb(null, { error : true, message : 'could not kill process w/o pid'});
328 }
329
330 God.killProcess(proc.process.pid, proc.pm2_env, function(err) {
331 proc.pm2_env.status = cst.STOPPED_STATUS;
332
333 God.notify('exit', proc);
334
335 if (err && err.type && err.type === 'timeout') {
336 console.error('app=%s id=%d pid=%s could not be stopped',
337 proc.pm2_env.name,
338 proc.pm2_env.pm_id,
339 proc.process.pid);
340 proc.pm2_env.status = cst.ERRORED_STATUS;
341 return cb(null, God.getFormatedProcess(id));
342 }
343
344 if (proc.pm2_env.pm_id.toString().indexOf('_old_') !== 0) {
345 try {
346 fs.unlinkSync(proc.pm2_env.pm_pid_path);
347 } catch (e) {}
348 }
349
350 if (proc.pm2_env.axm_actions) proc.pm2_env.axm_actions = [];
351 if (proc.pm2_env.axm_monitor) proc.pm2_env.axm_monitor = {};
352
353 proc.process.pid = 0;
354 return cb(null, God.getFormatedProcess(id));
355 });
356 };
357
358 God.resetMetaProcessId = function(id, cb) {
359 if (!(id in God.clusters_db))
360 return cb(God.logAndGenerateError(id + ' id unknown'), {});
361
362 if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env)
363 return cb(God.logAndGenerateError('Error when getting proc || proc.pm2_env'), {});
364
365 God.clusters_db[id].pm2_env.created_at = Utility.getDate();
366 God.clusters_db[id].pm2_env.unstable_restarts = 0;
367 God.clusters_db[id].pm2_env.restart_time = 0;
368
369 return cb(null, God.getFormatedProcesses());
370 };
371
372 /**
373 * Delete a process by id
374 * It will stop it and remove it from the database
375 * @method deleteProcessId
376 * @param {} id
377 * @param {} cb
378 * @return Literal
379 */
380 God.deleteProcessId = function(id, cb) {
381 God.deleteCron(id);
382
383 God.stopProcessId(id, function(err, proc) {
384 if (err) return cb(God.logAndGenerateError(err), {});
385 // ! transform to slow object
386 delete God.clusters_db[id];
387
388 if (Object.keys(God.clusters_db).length == 0)
389 God.next_id = 0;
390 return cb(null, proc);
391 });
392 return false;
393 };
394
395 /**
396 * Restart a process ID
397 * If the process is online it will not put it on state stopped
398 * but directly kill it and let God restart it
399 * @method restartProcessId
400 * @param {} id
401 * @param {} cb
402 * @return Literal
403 */
404 God.restartProcessId = function(opts, cb) {
405 var id = opts.id;
406 var env = opts.env || {};
407
408 if (typeof(id) === 'undefined')
409 return cb(God.logAndGenerateError('opts.id not passed to restartProcessId', opts));
410 if (!(id in God.clusters_db))
411 return cb(God.logAndGenerateError('God db process id unknown'), {});
412
413 var proc = God.clusters_db[id];
414
415 God.resetState(proc.pm2_env);
416
417 /**
418 * Merge new application configuration on restart
419 * Same system in reloadProcessId and softReloadProcessId
420 */
421 Utility.extend(proc.pm2_env.env, env);
422 Utility.extendExtraConfig(proc, opts);
423
424 if (God.pm2_being_killed) {
425 return cb(God.logAndGenerateError('[RestartProcessId] PM2 is being killed, stopping restart procedure...'));
426 }
427 if (proc.pm2_env.status === cst.ONLINE_STATUS || proc.pm2_env.status === cst.LAUNCHING_STATUS) {
428 God.stopProcessId(id, function(err) {
429 if (God.pm2_being_killed)
430 return cb(God.logAndGenerateError('[RestartProcessId] PM2 is being killed, stopping restart procedure...'));
431 proc.pm2_env.restart_time += 1;
432 return God.startProcessId(id, cb);
433 });
434
435 return false;
436 }
437 else {
438 debug('[restart] process not online, starting it');
439 return God.startProcessId(id, cb);
440 }
441 };
442
443
444 /**
445 * Restart all process by name
446 * @method restartProcessName
447 * @param {} name
448 * @param {} cb
449 * @return Literal
450 */
451 God.restartProcessName = function(name, cb) {
452 var processes = God.findByName(name);
453
454 if (processes && processes.length === 0)
455 return cb(God.logAndGenerateError('Unknown process'), {});
456
457 eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) {
458 if (God.pm2_being_killed)
459 return next('[Watch] PM2 is being killed, stopping restart procedure...');
460 if (proc.pm2_env.status === cst.ONLINE_STATUS)
461 return God.restartProcessId({id:proc.pm2_env.pm_id}, next);
462 else if (proc.pm2_env.status !== cst.STOPPING_STATUS
463 && proc.pm2_env.status !== cst.LAUNCHING_STATUS)
464 return God.startProcessId(proc.pm2_env.pm_id, next);
465 else
466 return next(util.format('[Watch] Process name %s is being stopped so I won\'t restart it', name));
467 }, function(err) {
468 if (err) return cb(God.logAndGenerateError(err));
469 return cb(null, God.getFormatedProcesses());
470 });
471
472 return false;
473 };
474
475 /**
476 * Send system signal to process id
477 * @method sendSignalToProcessId
478 * @param {} opts
479 * @param {} cb
480 * @return CallExpression
481 */
482 God.sendSignalToProcessId = function(opts, cb) {
483 var id = opts.process_id;
484 var signal = opts.signal;
485
486 if (!(id in God.clusters_db))
487 return cb(God.logAndGenerateError(id + ' id unknown'), {});
488
489 var proc = God.clusters_db[id];
490
491 //God.notify('send signal ' + signal, proc, true);
492
493 try {
494 process.kill(God.clusters_db[id].process.pid, signal);
495 } catch(e) {
496 return cb(God.logAndGenerateError('Error when sending signal (signal unknown)'), {});
497 }
498 return cb(null, God.getFormatedProcesses());
499 };
500
501 /**
502 * Send system signal to all processes by name
503 * @method sendSignalToProcessName
504 * @param {} opts
505 * @param {} cb
506 * @return
507 */
508 God.sendSignalToProcessName = function(opts, cb) {
509 var processes = God.findByName(opts.process_name);
510 var signal = opts.signal;
511
512 if (processes && processes.length === 0)
513 return cb(God.logAndGenerateError('Unknown process name'), {});
514
515 eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) {
516 if (proc.pm2_env.status == cst.ONLINE_STATUS || proc.pm2_env.status == cst.LAUNCHING_STATUS) {
517 try {
518 process.kill(proc.process.pid, signal);
519 } catch(e) {
520 return next(e);
521 }
522 }
523 return setTimeout(next, 200);
524 }, function(err) {
525 if (err) return cb(God.logAndGenerateError(err), {});
526 return cb(null, God.getFormatedProcesses());
527 });
528
529 };
530
531 /**
532 * Stop watching daemon
533 * @method stopWatch
534 * @param {} method
535 * @param {} value
536 * @param {} fn
537 * @return
538 */
539 God.stopWatch = function(method, value, fn) {
540 var env = null;
541
542 if (method == 'stopAll' || method == 'deleteAll') {
543 var processes = God.getFormatedProcesses();
544
545 processes.forEach(function(proc) {
546 God.clusters_db[proc.pm_id].pm2_env.watch = false;
547 God.watch.disable(proc.pm2_env);
548 });
549
550 } else {
551
552 if (method.indexOf('ProcessId') !== -1) {
553 env = God.clusters_db[value];
554 } else if (method.indexOf('ProcessName') !== -1) {
555 env = God.clusters_db[God.findByName(value)];
556 }
557
558 if (env) {
559 God.watch.disable(env.pm2_env);
560 env.pm2_env.watch = false;
561 }
562 }
563 return fn(null, {success:true});
564 };
565
566
567 /**
568 * Toggle watching daemon
569 * @method toggleWatch
570 * @param {String} method
571 * @param {Object} application environment, should include id
572 * @param {Function} callback
573 */
574 God.toggleWatch = function(method, value, fn) {
575 var env = null;
576
577 if (method == 'restartProcessId') {
578 env = God.clusters_db[value.id];
579 } else if(method == 'restartProcessName') {
580 env = God.clusters_db[God.findByName(value)];
581 }
582
583 if (env) {
584 env.pm2_env.watch = !env.pm2_env.watch;
585 if (env.pm2_env.watch)
586 God.watch.enable(env.pm2_env);
587 else
588 God.watch.disable(env.pm2_env);
589 }
590
591 return fn(null, {success:true});
592 };
593
594 /**
595 * Start Watch
596 * @method startWatch
597 * @param {String} method
598 * @param {Object} application environment, should include id
599 * @param {Function} callback
600 */
601 God.startWatch = function(method, value, fn) {
602 var env = null;
603
604 if (method == 'restartProcessId') {
605 env = God.clusters_db[value.id];
606 } else if(method == 'restartProcessName') {
607 env = God.clusters_db[God.findByName(value)];
608 }
609
610 if (env) {
611 if (env.pm2_env.watch)
612 return fn(null, {success:true, notrestarted:true});
613
614 God.watch.enable(env.pm2_env);
615 //env.pm2_env.env.watch = true;
616 env.pm2_env.watch = true;
617 }
618
619 return fn(null, {success:true});
620 };
621
622 /**
623 * Description
624 * @method reloadLogs
625 * @param {} opts
626 * @param {} cb
627 * @return CallExpression
628 */
629 God.reloadLogs = function(opts, cb) {
630 console.log('Reloading logs...');
631 var processIds = Object.keys(God.clusters_db);
632
633 processIds.forEach(function (id) {
634 var cluster = God.clusters_db[id];
635
636 console.log('Reloading logs for process id %d', id);
637
638 if (cluster && cluster.pm2_env) {
639 // Cluster mode
640 if (cluster.send && cluster.pm2_env.exec_mode == 'cluster_mode') {
641 try {
642 cluster.send({
643 type:'log:reload'
644 });
645 } catch(e) {
646 console.error(e.message || e);
647 }
648 }
649 // Fork mode
650 else if (cluster._reloadLogs) {
651 cluster._reloadLogs(function(err) {
652 if (err) God.logAndGenerateError(err);
653 });
654 }
655 }
656 });
657
658 return cb(null, {});
659 };
660
661 /**
662 * Send Line To Stdin
663 * @method sendLineToStdin
664 * @param Object packet
665 * @param String pm_id Process ID
666 * @param String line Line to send to process stdin
667 */
668 God.sendLineToStdin = function(packet, cb) {
669 if (typeof(packet.pm_id) == 'undefined' || !packet.line)
670 return cb(God.logAndGenerateError('pm_id or line field missing'), {});
671
672 var pm_id = packet.pm_id;
673 var line = packet.line;
674
675 var proc = God.clusters_db[pm_id];
676
677 if (!proc)
678 return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> unknown.'), {});
679
680 if (proc.pm2_env.exec_mode == 'cluster_mode')
681 return cb(God.logAndGenerateError('Cannot send line to processes in cluster mode'), {});
682
683 if (proc.pm2_env.status != cst.ONLINE_STATUS && proc.pm2_env.status != cst.LAUNCHING_STATUS)
684 return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> offline.'), {});
685
686 try {
687 proc.stdin.write(line, function() {
688 return cb(null, {
689 pm_id : pm_id,
690 line : line
691 });
692 });
693 } catch(e) {
694 return cb(God.logAndGenerateError(e), {});
695 }
696 }
697
698 /**
699 * @param {object} packet
700 * @param {function} cb
701 */
702 God.sendDataToProcessId = function(packet, cb) {
703 if (typeof(packet.id) == 'undefined' ||
704 typeof(packet.data) == 'undefined' ||
705 !packet.topic)
706 return cb(God.logAndGenerateError('ID, DATA or TOPIC field is missing'), {});
707
708 var pm_id = packet.id;
709 var data = packet.data;
710
711 var proc = God.clusters_db[pm_id];
712
713 if (!proc)
714 return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> unknown.'), {});
715
716 if (proc.pm2_env.status != cst.ONLINE_STATUS && proc.pm2_env.status != cst.LAUNCHING_STATUS)
717 return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> offline.'), {});
718
719 try {
720 proc.send(packet);
721 }
722 catch(e) {
723 return cb(God.logAndGenerateError(e), {});
724 }
725
726 return cb(null, {
727 success: true,
728 data : packet
729 });
730 };
731
732 /**
733 * Send Message to Process by id or name
734 * @method msgProcess
735 * @param {} cmd
736 * @param {} cb
737 * @return Literal
738 */
739 God.msgProcess = function(cmd, cb) {
740 if ('id' in cmd) {
741 var id = cmd.id;
742 if (!(id in God.clusters_db))
743 return cb(God.logAndGenerateError(id + ' id unknown'), {});
744 var proc = God.clusters_db[id];
745
746 var action_exist = false;
747
748 proc.pm2_env.axm_actions.forEach(function(action) {
749 if (action.action_name == cmd.msg) {
750 action_exist = true;
751 // Reset output buffer
752 action.output = [];
753 }
754 });
755 if (action_exist == false) {
756 return cb(God.logAndGenerateError('Action doesn\'t exist ' + cmd.msg + ' for ' + proc.pm2_env.name), {});
757 }
758
759 if (proc.pm2_env.status == cst.ONLINE_STATUS || proc.pm2_env.status == cst.LAUNCHING_STATUS) {
760 /*
761 * Send message
762 */
763 if (cmd.opts == null && !cmd.uuid)
764 proc.send(cmd.msg);
765 else
766 proc.send(cmd);
767
768 return cb(null, { process_count : 1, success : true });
769 }
770 else
771 return cb(God.logAndGenerateError(id + ' : id offline'), {});
772 }
773
774 else if ('name' in cmd) {
775 /*
776 * As names are not unique in case of cluster, this
777 * will send msg to all process matching 'name'
778 */
779 var name = cmd.name;
780 var arr = Object.keys(God.clusters_db);
781 var sent = 0;
782
783 (function ex(arr) {
784 if (arr[0] == null || !arr) {
785 return cb(null, {
786 process_count : sent,
787 success : true
788 });
789 }
790
791 var id = arr[0];
792
793 if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env) {
794 arr.shift();
795 return ex(arr);
796 }
797
798 var proc_env = God.clusters_db[id].pm2_env;
799
800 const isActionAvailable = proc_env.axm_actions.find(action => action.action_name === cmd.msg) !== undefined
801
802 // if action doesn't exist for this app
803 // try with the next one
804 if (isActionAvailable === false) {
805 arr.shift();
806 return ex(arr);
807 }
808
809
810 if ((p.basename(proc_env.pm_exec_path) == name ||
811 proc_env.name == name ||
812 proc_env.namespace == name ||
813 name == 'all') &&
814 (proc_env.status == cst.ONLINE_STATUS ||
815 proc_env.status == cst.LAUNCHING_STATUS)) {
816
817 proc_env.axm_actions.forEach(function(action) {
818 if (action.action_name == cmd.msg) {
819 action_exist = true;
820 }
821 });
822
823 if (action_exist == false || proc_env.axm_actions.length == 0) {
824 arr.shift();
825 return ex(arr);
826 }
827
828 if (cmd.opts == null)
829 God.clusters_db[id].send(cmd.msg);
830 else
831 God.clusters_db[id].send(cmd);
832
833 sent++;
834 arr.shift();
835 return ex(arr);
836 }
837 else {
838 arr.shift();
839 return ex(arr);
840 }
841 return false;
842 })(arr);
843 }
844
845 else return cb(God.logAndGenerateError('method requires name or id field'), {});
846 return false;
847 };
848
849 /**
850 * Description
851 * @method getVersion
852 * @param {} env
853 * @param {} cb
854 * @return CallExpression
855 */
856 God.getVersion = function(env, cb) {
857 process.nextTick(function() {
858 return cb(null, pkg.version);
859 });
860 };
861
862 God.monitor = function Monitor(pm_id, cb) {
863 if (!God.clusters_db[pm_id] || !God.clusters_db[pm_id].pm2_env)
864 return cb(new Error('Unknown pm_id'));
865
866 God.clusters_db[pm_id].pm2_env._km_monitored = true;
867 return cb(null, { success : true, pm_id : pm_id });
868 }
869
870 God.unmonitor = function Monitor(pm_id, cb) {
871 if (!God.clusters_db[pm_id] || !God.clusters_db[pm_id].pm2_env)
872 return cb(new Error('Unknown pm_id'));
873
874 God.clusters_db[pm_id].pm2_env._km_monitored = false;
875 return cb(null, { success : true, pm_id : pm_id });
876 }
877
878 God.getReport = function(arg, cb) {
879 var report = {
880 pm2_version : pkg.version,
881 node_version : 'N/A',
882 node_path : process.env['_'] || 'not found',
883 argv0 : process.argv0,
884 argv : process.argv,
885 user : process.env.USER,
886 uid : (cst.IS_WINDOWS === false && process.geteuid) ? process.geteuid() : 'N/A',
887 gid : (cst.IS_WINDOWS === false && process.getegid) ? process.getegid() : 'N/A',
888 env : process.env,
889 managed_apps : Object.keys(God.clusters_db).length,
890 started_at : God.started_at
891 };
892
893 if (process.versions && process.versions.node) {
894 report.node_version = process.versions.node;
895 }
896
897 process.nextTick(function() {
898 return cb(null, report);
899 });
900 };
901};
902
903function filterBadProcess(pro) {
904 if (pro.pm2_env.status !== cst.ONLINE_STATUS) {
905 return false;
906 }
907
908 if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) {
909 if (isNaN(pro.pm2_env.axm_options.pid)) {
910 return false;
911 }
912 }
913
914 return true;
915}
916
917function getProcessId(pro) {
918 var pid = pro.pid
919
920 if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) {
921 pid = pro.pm2_env.axm_options.pid;
922 }
923
924 return pid
925}