UNPKG

6.75 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 Utilities for PM2
10 * @author Alexandre Strzelewicz <as@unitech.io>
11 * @project PM2
12 */
13var p = require('path');
14var treekill = require('../TreeKill');
15var cst = require('../../constants.js');
16
17/**
18 * Description
19 * @method exports
20 * @param {} God
21 * @return
22 */
23module.exports = function(God) {
24
25 /**
26 * Description
27 * @method logAndGenerateError
28 * @param {} err
29 * @return NewExpression
30 */
31 God.logAndGenerateError = function(err) {
32 // Is an Error object
33 if (err instanceof Error) {
34 console.trace(err);
35 return err;
36 }
37 // Is a JSON or simple string
38 console.error(err);
39 return new Error(err);
40 };
41
42 /**
43 * Utility functions
44 * @method getProcesses
45 * @return MemberExpression
46 */
47 God.getProcesses = function() {
48 return God.clusters_db;
49 };
50
51 God.getFormatedProcess = function getFormatedProcesses(id) {
52 if (God.clusters_db[id])
53 return {
54 pid : God.clusters_db[id].process.pid,
55 name : God.clusters_db[id].pm2_env.name,
56 pm2_env : God.clusters_db[id].pm2_env,
57 pm_id : God.clusters_db[id].pm2_env.pm_id
58 };
59 return {};
60 };
61
62 /**
63 * Get formated processes
64 * @method getFormatedProcesses
65 * @return {Array} formated processes
66 */
67 God.getFormatedProcesses = function getFormatedProcesses() {
68 var keys = Object.keys(God.clusters_db);
69 var arr = new Array();
70 var kl = keys.length;
71
72 for (var i = 0; i < kl; i++) {
73 var key = keys[i];
74
75 if (!God.clusters_db[key]) continue;
76 // Avoid _old type pm_ids
77 if (isNaN(God.clusters_db[key].pm2_env.pm_id)) continue;
78
79 arr.push({
80 pid : God.clusters_db[key].process.pid,
81 name : God.clusters_db[key].pm2_env.name,
82 pm2_env : God.clusters_db[key].pm2_env,
83 pm_id : God.clusters_db[key].pm2_env.pm_id
84 })
85 }
86 return arr;
87 };
88
89 /**
90 * Description
91 * @method findProcessById
92 * @param {} id
93 * @return ConditionalExpression
94 */
95 God.findProcessById = function findProcessById(id) {
96 return God.clusters_db[id] ? God.clusters_db[id] : null;
97 };
98
99 /**
100 * Description
101 * @method findByName
102 * @param {} name
103 * @return arr
104 */
105 God.findByName = function(name) {
106 var db = God.clusters_db;
107 var arr = [];
108
109 if (name == 'all') {
110 for (var key in db) {
111 // Avoid _old_proc process style
112 if (typeof(God.clusters_db[key].pm2_env.pm_id) === 'number')
113 arr.push(db[key]);
114 }
115 return arr;
116 }
117
118 for (var key in db) {
119 if (God.clusters_db[key].pm2_env.name == name ||
120 God.clusters_db[key].pm2_env.pm_exec_path == p.resolve(name)) {
121 arr.push(db[key]);
122 }
123 }
124 return arr;
125 };
126
127 /**
128 * Check if a process is alive in system processes
129 * Return TRUE if process online
130 * @method checkProcess
131 * @param {} pid
132 * @return
133 */
134 God.checkProcess = function(pid) {
135 if (!pid) return false;
136
137 try {
138 // Sending 0 signal do not kill the process
139 process.kill(pid, 0);
140 return true;
141 }
142 catch (err) {
143 return false;
144 }
145 };
146
147 /**
148 * Description
149 * @method processIsDead
150 * @param {} pid
151 * @param {} cb
152 * @return Literal
153 */
154 God.processIsDead = function(pid, pm2_env, cb, sigkill) {
155 if (!pid) return cb({type : 'param:missing', msg : 'no pid passed'});
156
157 var timeout = null;
158 var kill_timeout = (pm2_env && pm2_env.kill_timeout) ? pm2_env.kill_timeout : cst.KILL_TIMEOUT;
159 var mode = pm2_env.exec_mode;
160
161 var timer = setInterval(function() {
162 if (God.checkProcess(pid) === false) {
163 console.log('pid=%d msg=process killed', pid);
164 clearTimeout(timeout);
165 clearInterval(timer);
166 return cb(null, true);
167 }
168 console.log('pid=%d msg=failed to kill - retrying in %dms', pid, pm2_env.kill_retry_time);
169 return false;
170 }, pm2_env.kill_retry_time);
171
172 timeout = setTimeout(function() {
173 clearInterval(timer);
174 if (sigkill) {
175 console.log('Process with pid %d could not be killed', pid);
176 return cb({type : 'timeout', msg : 'timeout'});
177 }
178 else {
179 console.log('Process with pid %d still alive after %sms, sending it SIGKILL now...', pid, kill_timeout);
180
181 if (pm2_env.treekill !== true) {
182 try {
183 process.kill(parseInt(pid), 'SIGKILL');
184 } catch(e) {
185 console.error('[SimpleKill][SIGKILL] %s pid can not be killed', pid, e.stack, e.message);
186 }
187 return God.processIsDead(pid, pm2_env, cb, true);
188 }
189 else {
190 treekill(parseInt(pid), 'SIGKILL', function(err) {
191 return God.processIsDead(pid, pm2_env, cb, true);
192 });
193 }
194 }
195 }, kill_timeout);
196 return false;
197 };
198
199 /**
200 * Description
201 * @method killProcess
202 * @param int pid
203 * @param Object pm2_env
204 * @param function cb
205 * @return CallExpression
206 */
207 God.killProcess = function(pid, pm2_env, cb) {
208 if (!pid) return cb({msg : 'no pid passed or null'});
209
210 if (typeof(pm2_env.pm_id) === 'number' &&
211 (cst.KILL_USE_MESSAGE || pm2_env.shutdown_with_message == true)) {
212 var proc = God.clusters_db[pm2_env.pm_id];
213
214 if (proc && proc.send) {
215 try {
216 proc.send('shutdown');
217 } catch (e) {
218 console.error(`[AppKill] Cannot send "shutdown" message to ${pid}`)
219 console.error(e.stack, e.message)
220 }
221 return God.processIsDead(pid, pm2_env, cb);
222 }
223 else {
224 console.log(`[AppKill] ${pid} pid cannot be notified with send()`)
225 }
226 }
227
228 if (pm2_env.treekill !== true) {
229 try {
230 process.kill(parseInt(pid), cst.KILL_SIGNAL);
231 } catch(e) {
232 console.error('[SimpleKill] %s pid can not be killed', pid, e.stack, e.message);
233 }
234 return God.processIsDead(pid, pm2_env, cb);
235 }
236 else {
237 treekill(parseInt(pid), cst.KILL_SIGNAL, function(err) {
238 return God.processIsDead(pid, pm2_env, cb);
239 });
240 }
241 };
242
243 /**
244 * Description
245 * @method getNewId
246 * @return UpdateExpression
247 */
248 God.getNewId = function() {
249 return God.next_id++;
250 };
251
252 /**
253 * When a process is restarted or reloaded reset fields
254 * to monitor unstable starts
255 * @method resetState
256 * @param {} pm2_env
257 * @return
258 */
259 God.resetState = function(pm2_env) {
260 pm2_env.created_at = Date.now();
261 pm2_env.unstable_restarts = 0;
262 pm2_env.prev_restart_delay = 0;
263 };
264
265};