@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.
- package/.claude/settings.local.json +8 -0
- package/.gitattributes +4 -0
- package/.mocharc.js +14 -0
- package/CHANGELOG.md +2416 -0
- package/CLAUDE.md +84 -0
- package/CONTRIBUTING.md +124 -0
- package/GNU-AGPL-3.0.txt +665 -0
- package/LICENSE +1 -0
- package/README.md +248 -0
- package/bin/zm2 +3 -0
- package/bin/zm2-dev +3 -0
- package/bin/zm2-docker +3 -0
- package/bin/zm2-runtime +3 -0
- package/bin/zm2-windows +3 -0
- package/bin/zm2.ps1 +3 -0
- package/bun.lock +421 -0
- package/constants.js +114 -0
- package/index.js +13 -0
- package/lib/API/Configuration.js +212 -0
- package/lib/API/Containerizer.js +335 -0
- package/lib/API/Dashboard.js +459 -0
- package/lib/API/Deploy.js +117 -0
- package/lib/API/Extra.js +775 -0
- package/lib/API/ExtraMgmt/Docker.js +30 -0
- package/lib/API/Log.js +315 -0
- package/lib/API/LogManagement.js +371 -0
- package/lib/API/Modules/LOCAL.js +122 -0
- package/lib/API/Modules/Modularizer.js +148 -0
- package/lib/API/Modules/NPM.js +445 -0
- package/lib/API/Modules/TAR.js +362 -0
- package/lib/API/Modules/flagExt.js +46 -0
- package/lib/API/Modules/index.js +120 -0
- package/lib/API/Monit.js +247 -0
- package/lib/API/Serve.js +343 -0
- package/lib/API/Startup.js +629 -0
- package/lib/API/UX/helpers.js +213 -0
- package/lib/API/UX/index.js +9 -0
- package/lib/API/UX/pm2-describe.js +193 -0
- package/lib/API/UX/pm2-ls-minimal.js +31 -0
- package/lib/API/UX/pm2-ls.js +483 -0
- package/lib/API/Version.js +382 -0
- package/lib/API/interpreter.json +12 -0
- package/lib/API/pm2-plus/PM2IO.js +372 -0
- package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
- package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
- package/lib/API/pm2-plus/helpers.js +97 -0
- package/lib/API/pm2-plus/link.js +126 -0
- package/lib/API/pm2-plus/pres/motd +16 -0
- package/lib/API/pm2-plus/pres/motd.update +26 -0
- package/lib/API/pm2-plus/pres/welcome +28 -0
- package/lib/API/pm2-plus/process-selector.js +52 -0
- package/lib/API/schema.json +379 -0
- package/lib/API.js +1931 -0
- package/lib/Client.js +776 -0
- package/lib/Common.js +911 -0
- package/lib/Configuration.js +304 -0
- package/lib/Daemon.js +456 -0
- package/lib/Event.js +37 -0
- package/lib/God/ActionMethods.js +909 -0
- package/lib/God/ClusterMode.js +97 -0
- package/lib/God/ForkMode.js +297 -0
- package/lib/God/Methods.js +265 -0
- package/lib/God/Reload.js +240 -0
- package/lib/God.js +632 -0
- package/lib/HttpInterface.js +76 -0
- package/lib/ProcessContainer.js +305 -0
- package/lib/ProcessContainerBun.js +360 -0
- package/lib/ProcessContainerFork.js +42 -0
- package/lib/ProcessContainerForkBun.js +33 -0
- package/lib/ProcessUtils.js +55 -0
- package/lib/TreeKill.js +118 -0
- package/lib/Utility.js +430 -0
- package/lib/VersionCheck.js +46 -0
- package/lib/Watcher.js +117 -0
- package/lib/Worker.js +169 -0
- package/lib/binaries/CLI.js +1041 -0
- package/lib/binaries/DevCLI.js +183 -0
- package/lib/binaries/Runtime.js +101 -0
- package/lib/binaries/Runtime4Docker.js +192 -0
- package/lib/completion.js +229 -0
- package/lib/completion.sh +40 -0
- package/lib/motd +36 -0
- package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
- package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
- package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
- package/lib/templates/ecosystem-es.tpl +24 -0
- package/lib/templates/ecosystem-simple-es.tpl +8 -0
- package/lib/templates/ecosystem-simple.tpl +6 -0
- package/lib/templates/ecosystem.tpl +22 -0
- package/lib/templates/init-scripts/launchd.tpl +35 -0
- package/lib/templates/init-scripts/openrc.tpl +52 -0
- package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
- package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
- package/lib/templates/init-scripts/rcd.tpl +44 -0
- package/lib/templates/init-scripts/smf.tpl +43 -0
- package/lib/templates/init-scripts/systemd-online.tpl +22 -0
- package/lib/templates/init-scripts/systemd.tpl +22 -0
- package/lib/templates/init-scripts/upstart.tpl +103 -0
- package/lib/templates/logrotate.d/pm2 +10 -0
- package/lib/templates/sample-apps/http-server/README.md +14 -0
- package/lib/templates/sample-apps/http-server/api.js +9 -0
- package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
- package/lib/templates/sample-apps/http-server/package.json +11 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
- package/lib/templates/sample-apps/python-app/README.md +4 -0
- package/lib/templates/sample-apps/python-app/echo.py +7 -0
- package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
- package/lib/templates/sample-apps/python-app/package.json +11 -0
- package/lib/tools/Config.js +248 -0
- package/lib/tools/IsAbsolute.js +20 -0
- package/lib/tools/copydirSync.js +101 -0
- package/lib/tools/deleteFolderRecursive.js +19 -0
- package/lib/tools/find-package-json.js +74 -0
- package/lib/tools/fmt.js +72 -0
- package/lib/tools/isbinaryfile.js +94 -0
- package/lib/tools/json5.js +752 -0
- package/lib/tools/open.js +63 -0
- package/lib/tools/passwd.js +58 -0
- package/lib/tools/promise.min.js +1 -0
- package/lib/tools/sexec.js +55 -0
- package/lib/tools/treeify.js +113 -0
- package/lib/tools/which.js +120 -0
- package/lib/tools/xdg-open +861 -0
- package/package.json +219 -0
- package/paths.js +93 -0
- package/pm2 +11 -0
- package/preinstall.js +24 -0
- package/run.sh +9 -0
- package/types/index.d.ts +722 -0
- package/types/tsconfig.json +14 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 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 Cluster execution functions related
|
|
10
|
+
* @author Alexandre Strzelewicz <as@unitech.io>
|
|
11
|
+
* @project PM2
|
|
12
|
+
*/
|
|
13
|
+
var cluster = require('cluster');
|
|
14
|
+
var Utility = require('../Utility.js');
|
|
15
|
+
var pkg = require('../../package.json');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Description
|
|
19
|
+
* @method exports
|
|
20
|
+
* @param {} God
|
|
21
|
+
* @return
|
|
22
|
+
*/
|
|
23
|
+
module.exports = function ClusterMode(God) {
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* For Node apps - Cluster mode
|
|
27
|
+
* It will wrap the code and enable load-balancing mode
|
|
28
|
+
* @method nodeApp
|
|
29
|
+
* @param {} env_copy
|
|
30
|
+
* @param {} cb
|
|
31
|
+
* @return Literal
|
|
32
|
+
*/
|
|
33
|
+
God.nodeApp = function nodeApp(env_copy, cb){
|
|
34
|
+
var clu = null;
|
|
35
|
+
|
|
36
|
+
console.log(`App [${env_copy.name}:${env_copy.pm_id}] starting in -cluster mode-`)
|
|
37
|
+
if (env_copy.node_args && Array.isArray(env_copy.node_args)) {
|
|
38
|
+
cluster.settings.execArgv = env_copy.node_args;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
env_copy._pm2_version = pkg.version;
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
// node.js cluster clients can not receive deep-level objects or arrays in the forked process, e.g.:
|
|
45
|
+
// { "args": ["foo", "bar"], "env": { "foo1": "bar1" }} will be parsed to
|
|
46
|
+
// { "args": "foo, bar", "env": "[object Object]"}
|
|
47
|
+
// So we passing a stringified JSON here.
|
|
48
|
+
clu = cluster.fork({pm2_env: JSON.stringify(env_copy), windowsHide: true});
|
|
49
|
+
} catch(e) {
|
|
50
|
+
God.logAndGenerateError(e);
|
|
51
|
+
return cb(e);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
clu.pm2_env = env_copy;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Broadcast message to God
|
|
58
|
+
*/
|
|
59
|
+
clu.on('message', function cluMessage(msg) {
|
|
60
|
+
/*********************************
|
|
61
|
+
* If you edit this function
|
|
62
|
+
* Do the same in ForkMode.js !
|
|
63
|
+
*********************************/
|
|
64
|
+
if (msg.data && msg.type) {
|
|
65
|
+
return God.bus.emit(msg.type ? msg.type : 'process:msg', {
|
|
66
|
+
at : Utility.getDate(),
|
|
67
|
+
data : msg.data,
|
|
68
|
+
process : {
|
|
69
|
+
pm_id : clu.pm2_env.pm_id,
|
|
70
|
+
name : clu.pm2_env.name,
|
|
71
|
+
rev : (clu.pm2_env.versioning && clu.pm2_env.versioning.revision) ? clu.pm2_env.versioning.revision : null,
|
|
72
|
+
namespace : clu.pm2_env.namespace
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
|
|
78
|
+
if (typeof msg == 'object' && 'node_version' in msg) {
|
|
79
|
+
clu.pm2_env.node_version = msg.node_version;
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return God.bus.emit('process:msg', {
|
|
84
|
+
at : Utility.getDate(),
|
|
85
|
+
raw : msg,
|
|
86
|
+
process : {
|
|
87
|
+
pm_id : clu.pm2_env.pm_id,
|
|
88
|
+
name : clu.pm2_env.name,
|
|
89
|
+
namespace : clu.pm2_env.namespace
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
return cb(null, clu);
|
|
96
|
+
};
|
|
97
|
+
};
|
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 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 Fork execution related functions
|
|
10
|
+
* @author Alexandre Strzelewicz <as@unitech.io>
|
|
11
|
+
* @project PM2
|
|
12
|
+
*/
|
|
13
|
+
var log = require('debug')('zm2:fork_mode');
|
|
14
|
+
var fs = require('fs');
|
|
15
|
+
var Utility = require('../Utility.js');
|
|
16
|
+
var path = require('path');
|
|
17
|
+
var dayjs = require('dayjs');
|
|
18
|
+
var semver = require('semver')
|
|
19
|
+
var cst = require('../../constants.js');
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Description
|
|
23
|
+
* @method exports
|
|
24
|
+
* @param {} God
|
|
25
|
+
* @return
|
|
26
|
+
*/
|
|
27
|
+
module.exports = function ForkMode(God) {
|
|
28
|
+
/**
|
|
29
|
+
* For all apps - FORK MODE
|
|
30
|
+
* fork the app
|
|
31
|
+
* @method forkMode
|
|
32
|
+
* @param {} pm2_env
|
|
33
|
+
* @param {} cb
|
|
34
|
+
* @return
|
|
35
|
+
*/
|
|
36
|
+
God.forkMode = function forkMode(pm2_env, cb) {
|
|
37
|
+
var command = '';
|
|
38
|
+
var args = [];
|
|
39
|
+
|
|
40
|
+
console.log(`App [${pm2_env.name}:${pm2_env.pm_id}] starting in -fork mode-`)
|
|
41
|
+
var spawn = require('child_process').spawn;
|
|
42
|
+
|
|
43
|
+
var interpreter = pm2_env.exec_interpreter || process.execPath;
|
|
44
|
+
var pidFile = pm2_env.pm_pid_path;
|
|
45
|
+
|
|
46
|
+
if (interpreter !== 'none') {
|
|
47
|
+
command = interpreter;
|
|
48
|
+
|
|
49
|
+
if (pm2_env.node_args && Array.isArray(pm2_env.node_args)) {
|
|
50
|
+
args = args.concat(pm2_env.node_args);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Deprecated - to remove at some point
|
|
54
|
+
if (process.env.PM2_NODE_OPTIONS) {
|
|
55
|
+
args = args.concat(process.env.PM2_NODE_OPTIONS.split(' '));
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (interpreter === 'node' || RegExp('node$').test(interpreter)) {
|
|
59
|
+
args.push(path.resolve(path.dirname(module.filename), '..', 'ProcessContainerFork.js'));
|
|
60
|
+
}
|
|
61
|
+
else if (interpreter.includes('bun') === true) {
|
|
62
|
+
args.push(path.resolve(path.dirname(module.filename), '..', 'ProcessContainerForkBun.js'));
|
|
63
|
+
}
|
|
64
|
+
else
|
|
65
|
+
args.push(pm2_env.pm_exec_path);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
command = pm2_env.pm_exec_path;
|
|
69
|
+
args = [ ];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (pm2_env.args) {
|
|
73
|
+
args = args.concat(pm2_env.args);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// piping stream o file
|
|
77
|
+
var stds = {
|
|
78
|
+
out: pm2_env.pm_out_log_path,
|
|
79
|
+
err: pm2_env.pm_err_log_path
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
// entire log std if necessary.
|
|
83
|
+
if ('pm_log_path' in pm2_env){
|
|
84
|
+
stds.std = pm2_env.pm_log_path;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
log("stds: %j", stds);
|
|
88
|
+
|
|
89
|
+
Utility.startLogging(stds, pm2_env, function(err, result) {
|
|
90
|
+
if (err) {
|
|
91
|
+
God.logAndGenerateError(err);
|
|
92
|
+
return cb(err);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
try {
|
|
96
|
+
var options = {
|
|
97
|
+
env : pm2_env,
|
|
98
|
+
detached : true,
|
|
99
|
+
cwd : pm2_env.pm_cwd || process.cwd(),
|
|
100
|
+
stdio : ['pipe', 'pipe', 'pipe', 'ipc'] //Same as fork() in node core
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
if (typeof(pm2_env.windowsHide) === "boolean") {
|
|
104
|
+
options.windowsHide = pm2_env.windowsHide;
|
|
105
|
+
} else {
|
|
106
|
+
options.windowsHide = true;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (pm2_env.uid) {
|
|
110
|
+
options.uid = pm2_env.uid
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
if (pm2_env.gid) {
|
|
114
|
+
options.gid = pm2_env.gid
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
var cspr = spawn(command, args, options);
|
|
118
|
+
} catch(e) {
|
|
119
|
+
God.logAndGenerateError(e);
|
|
120
|
+
return cb(e);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
if (!cspr || !cspr.stderr || !cspr.stdout) {
|
|
124
|
+
var fatalError = new Error('Process could not be forked properly, check your system health')
|
|
125
|
+
God.logAndGenerateError(fatalError);
|
|
126
|
+
return cb(fatalError);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
cspr.process = {};
|
|
130
|
+
cspr.process.pid = cspr.pid;
|
|
131
|
+
cspr.pm2_env = pm2_env;
|
|
132
|
+
|
|
133
|
+
function transformLogToJson(pm2_env, type, data) {
|
|
134
|
+
return JSON.stringify({
|
|
135
|
+
message : data.toString(),
|
|
136
|
+
timestamp : pm2_env.log_date_format ? dayjs().format(pm2_env.log_date_format) : new Date().toISOString(),
|
|
137
|
+
type : type,
|
|
138
|
+
process_id : cspr.pm2_env.pm_id,
|
|
139
|
+
app_name : cspr.pm2_env.name
|
|
140
|
+
}) + '\n'
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function prefixLogWithDate(pm2_env, data) {
|
|
144
|
+
var log_data = []
|
|
145
|
+
log_data = data.toString().split('\n')
|
|
146
|
+
if (log_data.length > 1)
|
|
147
|
+
log_data.pop()
|
|
148
|
+
log_data = log_data.map(line => `${dayjs().format(pm2_env.log_date_format)}: ${line}\n`)
|
|
149
|
+
log_data = log_data.join('')
|
|
150
|
+
return log_data
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
cspr.stderr.on('data', function forkErrData(data) {
|
|
154
|
+
var log_data = null;
|
|
155
|
+
|
|
156
|
+
// via --out /dev/null --err /dev/null
|
|
157
|
+
if (pm2_env.disable_logs === true) return false;
|
|
158
|
+
|
|
159
|
+
if (pm2_env.log_type && pm2_env.log_type === 'json')
|
|
160
|
+
log_data = transformLogToJson(pm2_env, 'err', data)
|
|
161
|
+
else if (pm2_env.log_date_format)
|
|
162
|
+
log_data = prefixLogWithDate(pm2_env, data)
|
|
163
|
+
else
|
|
164
|
+
log_data = data.toString();
|
|
165
|
+
|
|
166
|
+
God.bus.emit('log:err', {
|
|
167
|
+
process : {
|
|
168
|
+
pm_id : cspr.pm2_env.pm_id,
|
|
169
|
+
name : cspr.pm2_env.name,
|
|
170
|
+
rev : (cspr.pm2_env.versioning && cspr.pm2_env.versioning.revision) ? cspr.pm2_env.versioning.revision : null,
|
|
171
|
+
namespace : cspr.pm2_env.namespace
|
|
172
|
+
},
|
|
173
|
+
at : Utility.getDate(),
|
|
174
|
+
data : log_data
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
if (Utility.checkPathIsNull(pm2_env.pm_err_log_path) &&
|
|
178
|
+
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path))) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
stds.std && stds.std.write && stds.std.write(log_data);
|
|
183
|
+
stds.err && stds.err.write && stds.err.write(log_data);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
cspr.stdout.on('data', function forkOutData(data) {
|
|
187
|
+
var log_data = null;
|
|
188
|
+
|
|
189
|
+
if (pm2_env.disable_logs === true)
|
|
190
|
+
return false;
|
|
191
|
+
|
|
192
|
+
if (pm2_env.log_type && pm2_env.log_type === 'json')
|
|
193
|
+
log_data = transformLogToJson(pm2_env, 'out', data)
|
|
194
|
+
else if (pm2_env.log_date_format)
|
|
195
|
+
log_data = prefixLogWithDate(pm2_env, data)
|
|
196
|
+
else
|
|
197
|
+
log_data = data.toString()
|
|
198
|
+
|
|
199
|
+
God.bus.emit('log:out', {
|
|
200
|
+
process : {
|
|
201
|
+
pm_id : cspr.pm2_env.pm_id,
|
|
202
|
+
name : cspr.pm2_env.name,
|
|
203
|
+
rev : (cspr.pm2_env.versioning && cspr.pm2_env.versioning.revision) ? cspr.pm2_env.versioning.revision : null,
|
|
204
|
+
namespace : cspr.pm2_env.namespace
|
|
205
|
+
},
|
|
206
|
+
at : Utility.getDate(),
|
|
207
|
+
data : log_data
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
if (Utility.checkPathIsNull(pm2_env.pm_out_log_path) &&
|
|
211
|
+
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
|
|
212
|
+
return false;
|
|
213
|
+
|
|
214
|
+
stds.std && stds.std.write && stds.std.write(log_data);
|
|
215
|
+
stds.out && stds.out.write && stds.out.write(log_data);
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Broadcast message to God
|
|
220
|
+
*/
|
|
221
|
+
cspr.on('message', function forkMessage(msg) {
|
|
222
|
+
/*********************************
|
|
223
|
+
* If you edit this function
|
|
224
|
+
* Do the same in ClusterMode.js !
|
|
225
|
+
*********************************/
|
|
226
|
+
if (msg.data && msg.type) {
|
|
227
|
+
process.nextTick(function() {
|
|
228
|
+
return God.bus.emit(msg.type ? msg.type : 'process:msg', {
|
|
229
|
+
at : Utility.getDate(),
|
|
230
|
+
data : msg.data,
|
|
231
|
+
process : {
|
|
232
|
+
pm_id : cspr.pm2_env.pm_id,
|
|
233
|
+
name : cspr.pm2_env.name,
|
|
234
|
+
versioning : cspr.pm2_env.versioning,
|
|
235
|
+
namespace : cspr.pm2_env.namespace
|
|
236
|
+
}
|
|
237
|
+
});
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
|
|
242
|
+
if (typeof msg == 'object' && 'node_version' in msg) {
|
|
243
|
+
cspr.pm2_env.node_version = msg.node_version;
|
|
244
|
+
return false;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return God.bus.emit('process:msg', {
|
|
248
|
+
at : Utility.getDate(),
|
|
249
|
+
raw : msg,
|
|
250
|
+
process : {
|
|
251
|
+
pm_id : cspr.pm2_env.pm_id,
|
|
252
|
+
name : cspr.pm2_env.name,
|
|
253
|
+
namespace : cspr.pm2_env.namespace
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
var pid = cspr.pid
|
|
261
|
+
if (typeof(pid) !== 'undefined')
|
|
262
|
+
fs.writeFileSync(pidFile, pid.toString());
|
|
263
|
+
} catch (e) {
|
|
264
|
+
console.error(e.stack || e);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
cspr.once('exit', function forkClose(status) {
|
|
268
|
+
try {
|
|
269
|
+
for(var k in stds){
|
|
270
|
+
if (stds[k] && stds[k].destroy) stds[k].destroy();
|
|
271
|
+
else if (stds[k] && stds[k].end) stds[k].end();
|
|
272
|
+
else if (stds[k] && stds[k].close) stds[k].close();
|
|
273
|
+
stds[k] = stds[k]._file;
|
|
274
|
+
}
|
|
275
|
+
} catch(e) { God.logAndGenerateError(e);}
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
cspr._reloadLogs = function(cb) {
|
|
279
|
+
try {
|
|
280
|
+
for (var k in stds){
|
|
281
|
+
if (stds[k] && stds[k].destroy) stds[k].destroy();
|
|
282
|
+
else if (stds[k] && stds[k].end) stds[k].end();
|
|
283
|
+
else if (stds[k] && stds[k].close) stds[k].close();
|
|
284
|
+
stds[k] = stds[k]._file;
|
|
285
|
+
}
|
|
286
|
+
} catch(e) { God.logAndGenerateError(e);}
|
|
287
|
+
//cspr.removeAllListeners();
|
|
288
|
+
Utility.startLogging(stds, pm2_env, cb);
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
cspr.unref();
|
|
292
|
+
|
|
293
|
+
return cb(null, cspr);
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
};
|
|
297
|
+
};
|
|
@@ -0,0 +1,265 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 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
|
+
*/
|
|
13
|
+
var p = require('path');
|
|
14
|
+
var treekill = require('../TreeKill');
|
|
15
|
+
var cst = require('../../constants.js');
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Description
|
|
19
|
+
* @method exports
|
|
20
|
+
* @param {} God
|
|
21
|
+
* @return
|
|
22
|
+
*/
|
|
23
|
+
module.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
|
+
};
|