@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
package/lib/Daemon.js
ADDED
|
@@ -0,0 +1,456 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright 2013-2022 the ZM2 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
|
+
|
|
7
|
+
var debug = require('debug')('zm2:daemon');
|
|
8
|
+
var pkg = require('../package.json');
|
|
9
|
+
var cst = require('../constants.js');
|
|
10
|
+
var rpc = require('pm2-axon-rpc');
|
|
11
|
+
var axon = require('pm2-axon');
|
|
12
|
+
var domain = require('domain');
|
|
13
|
+
var Utility = require('./Utility.js');
|
|
14
|
+
var util = require('util');
|
|
15
|
+
var fs = require('fs');
|
|
16
|
+
var God = require('./God');
|
|
17
|
+
var eachLimit = require('async/eachLimit');
|
|
18
|
+
var fmt = require('./tools/fmt.js');
|
|
19
|
+
var semver = require('semver');
|
|
20
|
+
|
|
21
|
+
var Daemon = module.exports = function(opts) {
|
|
22
|
+
if (!opts) opts = {};
|
|
23
|
+
|
|
24
|
+
this.ignore_signals = opts.ignore_signals || false;
|
|
25
|
+
this.rpc_socket_ready = false;
|
|
26
|
+
this.pub_socket_ready = false;
|
|
27
|
+
|
|
28
|
+
this.pub_socket_file = opts.pub_socket_file || cst.DAEMON_PUB_PORT;
|
|
29
|
+
this.rpc_socket_file = opts.rpc_socket_file || cst.DAEMON_RPC_PORT;
|
|
30
|
+
|
|
31
|
+
this.pid_path = opts.pid_file || cst.PM2_PID_FILE_PATH;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
Daemon.prototype.start = function() {
|
|
35
|
+
var that = this;
|
|
36
|
+
var d = domain.create();
|
|
37
|
+
|
|
38
|
+
d.once('error', function(err) {
|
|
39
|
+
fmt.sep();
|
|
40
|
+
fmt.title('ZM2 global error caught');
|
|
41
|
+
fmt.field('Time', new Date());
|
|
42
|
+
console.error(err.message);
|
|
43
|
+
console.error(err.stack);
|
|
44
|
+
fmt.sep();
|
|
45
|
+
|
|
46
|
+
console.error('[ZM2] Resurrecting ZM2');
|
|
47
|
+
|
|
48
|
+
var path = cst.IS_WINDOWS ? __dirname + '/../bin/zm2' : process.env['_'];
|
|
49
|
+
var fork_new_pm2 = require('child_process').spawn('node', [path, 'update'], {
|
|
50
|
+
detached: true,
|
|
51
|
+
windowsHide: true,
|
|
52
|
+
stdio: 'inherit'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
fork_new_pm2.on('close', function() {
|
|
56
|
+
console.log('ZM2 successfully forked');
|
|
57
|
+
process.exit(0);
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
d.run(function() {
|
|
63
|
+
that.innerStart();
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
Daemon.prototype.innerStart = function(cb) {
|
|
68
|
+
var that = this;
|
|
69
|
+
|
|
70
|
+
if (!cb) cb = function() {
|
|
71
|
+
fmt.sep();
|
|
72
|
+
fmt.title('New ZM2 Daemon started');
|
|
73
|
+
fmt.field('Time', new Date());
|
|
74
|
+
fmt.field('ZM2 version', pkg.version);
|
|
75
|
+
fmt.field('Node.js version', process.versions.node);
|
|
76
|
+
fmt.field('Current arch', process.arch);
|
|
77
|
+
fmt.field('ZM2 home', cst.PM2_HOME);
|
|
78
|
+
fmt.field('ZM2 PID file', that.pid_path);
|
|
79
|
+
fmt.field('RPC socket file', that.rpc_socket_file);
|
|
80
|
+
fmt.field('BUS socket file', that.pub_socket_file);
|
|
81
|
+
fmt.field('Application log path', cst.DEFAULT_LOG_PATH);
|
|
82
|
+
fmt.field('Worker Interval', cst.WORKER_INTERVAL);
|
|
83
|
+
fmt.field('Process dump file', cst.DUMP_FILE_PATH);
|
|
84
|
+
fmt.field('Concurrent actions', cst.CONCURRENT_ACTIONS);
|
|
85
|
+
fmt.field('SIGTERM timeout', cst.KILL_TIMEOUT);
|
|
86
|
+
fmt.field('Runtime Binary', process.execPath);
|
|
87
|
+
fmt.sep();
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
// Write Daemon PID into file
|
|
91
|
+
try {
|
|
92
|
+
fs.writeFileSync(that.pid_path, process.pid.toString());
|
|
93
|
+
} catch (e) {
|
|
94
|
+
console.error(e.stack || e);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
if (this.ignore_signals != true)
|
|
98
|
+
this.handleSignals();
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Pub system for real time notifications
|
|
102
|
+
*/
|
|
103
|
+
this.pub = axon.socket('pub-emitter');
|
|
104
|
+
|
|
105
|
+
this.pub_socket = this.pub.bind(this.pub_socket_file);
|
|
106
|
+
|
|
107
|
+
this.pub_socket.once('bind', function() {
|
|
108
|
+
fs.chmod(that.pub_socket_file, '775', function(e) {
|
|
109
|
+
if (e) console.error(e);
|
|
110
|
+
|
|
111
|
+
try {
|
|
112
|
+
if (process.env.ZM2_SOCKET_USER && process.env.ZM2_SOCKET_GROUP)
|
|
113
|
+
fs.chown(that.pub_socket_file,
|
|
114
|
+
parseInt(process.env.ZM2_SOCKET_USER),
|
|
115
|
+
parseInt(process.env.ZM2_SOCKET_GROUP), function(e) {
|
|
116
|
+
if (e) console.error(e);
|
|
117
|
+
});
|
|
118
|
+
} catch(e) {
|
|
119
|
+
console.error(e);
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
that.pub_socket_ready = true;
|
|
124
|
+
that.sendReady(cb);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Rep/Req - RPC system to interact with God
|
|
129
|
+
*/
|
|
130
|
+
this.rep = axon.socket('rep');
|
|
131
|
+
|
|
132
|
+
var server = new rpc.Server(this.rep);
|
|
133
|
+
|
|
134
|
+
this.rpc_socket = this.rep.bind(this.rpc_socket_file);
|
|
135
|
+
|
|
136
|
+
this.rpc_socket.once('bind', function() {
|
|
137
|
+
fs.chmod(that.rpc_socket_file, '775', function(e) {
|
|
138
|
+
if (e) console.error(e);
|
|
139
|
+
|
|
140
|
+
try {
|
|
141
|
+
if (process.env.ZM2_SOCKET_USER && process.env.ZM2_SOCKET_GROUP)
|
|
142
|
+
fs.chown(that.rpc_socket_file,
|
|
143
|
+
parseInt(process.env.ZM2_SOCKET_USER),
|
|
144
|
+
parseInt(process.env.ZM2_SOCKET_GROUP), function(e) {
|
|
145
|
+
if (e) console.error(e);
|
|
146
|
+
});
|
|
147
|
+
} catch(e) {
|
|
148
|
+
console.error(e);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
that.rpc_socket_ready = true;
|
|
154
|
+
that.sendReady(cb);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Memory Snapshot
|
|
160
|
+
*/
|
|
161
|
+
function profile(type, msg, cb) {
|
|
162
|
+
if (semver.satisfies(process.version, '< 8'))
|
|
163
|
+
return cb(null, { error: 'Node.js is not on right version' })
|
|
164
|
+
|
|
165
|
+
var cmd
|
|
166
|
+
|
|
167
|
+
if (type === 'cpu') {
|
|
168
|
+
cmd = {
|
|
169
|
+
enable: 'Profiler.enable',
|
|
170
|
+
start: 'Profiler.start',
|
|
171
|
+
stop: 'Profiler.stop',
|
|
172
|
+
disable: 'Profiler.disable'
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (type == 'mem') {
|
|
176
|
+
cmd = {
|
|
177
|
+
enable: 'HeapProfiler.enable',
|
|
178
|
+
start: 'HeapProfiler.startSampling',
|
|
179
|
+
stop: 'HeapProfiler.stopSampling',
|
|
180
|
+
disable: 'HeapProfiler.disable'
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const inspector = require('inspector')
|
|
185
|
+
var session = new inspector.Session()
|
|
186
|
+
|
|
187
|
+
session.connect()
|
|
188
|
+
|
|
189
|
+
var timeout = msg.timeout || 5000
|
|
190
|
+
|
|
191
|
+
session.post(cmd.enable, (err, data) => {
|
|
192
|
+
if (err) return cb(null, { error: err.message || err })
|
|
193
|
+
|
|
194
|
+
console.log(`Starting ${cmd.start}`)
|
|
195
|
+
session.post(cmd.start, (err, data) => {
|
|
196
|
+
if (err) return cb(null, { error: err.message || err })
|
|
197
|
+
|
|
198
|
+
setTimeout(() => {
|
|
199
|
+
session.post(cmd.stop, (err, data) => {
|
|
200
|
+
if (err) return cb(null, { error: err.message || err })
|
|
201
|
+
const profile = data.profile
|
|
202
|
+
|
|
203
|
+
console.log(`Stopping ${cmd.stop}`)
|
|
204
|
+
session.post(cmd.disable)
|
|
205
|
+
|
|
206
|
+
fs.writeFile(msg.pwd, JSON.stringify(profile), (err) => {
|
|
207
|
+
if (err) return cb(null, { error: err.message || err })
|
|
208
|
+
return cb(null, { file : msg.pwd })
|
|
209
|
+
})
|
|
210
|
+
})
|
|
211
|
+
}, timeout)
|
|
212
|
+
})
|
|
213
|
+
})
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
server.expose({
|
|
217
|
+
killMe : that.close.bind(this),
|
|
218
|
+
profileCPU : profile.bind(this, 'cpu'),
|
|
219
|
+
profileMEM : profile.bind(this, 'mem'),
|
|
220
|
+
prepare : God.prepare,
|
|
221
|
+
getMonitorData : God.getMonitorData,
|
|
222
|
+
|
|
223
|
+
startProcessId : God.startProcessId,
|
|
224
|
+
stopProcessId : God.stopProcessId,
|
|
225
|
+
restartProcessId : God.restartProcessId,
|
|
226
|
+
deleteProcessId : God.deleteProcessId,
|
|
227
|
+
|
|
228
|
+
sendLineToStdin : God.sendLineToStdin,
|
|
229
|
+
softReloadProcessId : God.softReloadProcessId,
|
|
230
|
+
reloadProcessId : God.reloadProcessId,
|
|
231
|
+
duplicateProcessId : God.duplicateProcessId,
|
|
232
|
+
resetMetaProcessId : God.resetMetaProcessId,
|
|
233
|
+
stopWatch : God.stopWatch,
|
|
234
|
+
startWatch : God.startWatch,
|
|
235
|
+
toggleWatch : God.toggleWatch,
|
|
236
|
+
notifyByProcessId : God.notifyByProcessId,
|
|
237
|
+
|
|
238
|
+
notifyKillPM2 : God.notifyKillPM2,
|
|
239
|
+
monitor : God.monitor,
|
|
240
|
+
unmonitor : God.unmonitor,
|
|
241
|
+
|
|
242
|
+
msgProcess : God.msgProcess,
|
|
243
|
+
sendDataToProcessId : God.sendDataToProcessId,
|
|
244
|
+
sendSignalToProcessId : God.sendSignalToProcessId,
|
|
245
|
+
sendSignalToProcessName : God.sendSignalToProcessName,
|
|
246
|
+
|
|
247
|
+
ping : God.ping,
|
|
248
|
+
getVersion : God.getVersion,
|
|
249
|
+
getReport : God.getReport,
|
|
250
|
+
reloadLogs : God.reloadLogs
|
|
251
|
+
});
|
|
252
|
+
|
|
253
|
+
this.startLogic();
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
Daemon.prototype.close = function(opts, cb) {
|
|
257
|
+
var that = this;
|
|
258
|
+
|
|
259
|
+
God.bus.emit('zm2:kill', {
|
|
260
|
+
status : 'killed',
|
|
261
|
+
msg : 'zm2 has been killed via CLI'
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
if (God.system_infos_proc !== null)
|
|
265
|
+
God.system_infos_proc.kill()
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Cleanly kill zm2
|
|
269
|
+
*/
|
|
270
|
+
that.rpc_socket.close(function() {
|
|
271
|
+
that.pub_socket.close(function() {
|
|
272
|
+
|
|
273
|
+
// notify cli that the daemon is shuting down (only under unix since windows doesnt handle signals)
|
|
274
|
+
if (cst.IS_WINDOWS === false) {
|
|
275
|
+
try {
|
|
276
|
+
process.kill(parseInt(opts.pid), 'SIGQUIT');
|
|
277
|
+
} catch(e) {
|
|
278
|
+
console.error('Could not send SIGQUIT to CLI');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
try {
|
|
283
|
+
fs.unlinkSync(that.pid_path);
|
|
284
|
+
} catch(e) {}
|
|
285
|
+
|
|
286
|
+
console.log('ZM2 successfully stopped');
|
|
287
|
+
setTimeout(function() {
|
|
288
|
+
process.exit(cst.SUCCESS_EXIT);
|
|
289
|
+
}, 2);
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
Daemon.prototype.handleSignals = function() {
|
|
295
|
+
var that = this;
|
|
296
|
+
|
|
297
|
+
process.on('SIGTERM', that.gracefullExit.bind(this));
|
|
298
|
+
process.on('SIGINT', that.gracefullExit.bind(this));
|
|
299
|
+
process.on('SIGHUP', function() {});
|
|
300
|
+
process.on('SIGQUIT', that.gracefullExit.bind(this));
|
|
301
|
+
process.on('SIGUSR2', function() {
|
|
302
|
+
God.reloadLogs({}, function() {});
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
Daemon.prototype.sendReady = function(cb) {
|
|
307
|
+
// Send ready message to Client
|
|
308
|
+
if (this.rpc_socket_ready == true && this.pub_socket_ready == true) {
|
|
309
|
+
cb(null, {
|
|
310
|
+
pid : process.pid,
|
|
311
|
+
pm2_version : pkg.version
|
|
312
|
+
});
|
|
313
|
+
if (typeof(process.send) != 'function')
|
|
314
|
+
return false;
|
|
315
|
+
|
|
316
|
+
process.send({
|
|
317
|
+
online : true,
|
|
318
|
+
success : true,
|
|
319
|
+
pid : process.pid,
|
|
320
|
+
pm2_version : pkg.version
|
|
321
|
+
});
|
|
322
|
+
};
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
Daemon.prototype.gracefullExit = function() {
|
|
326
|
+
var that = this;
|
|
327
|
+
|
|
328
|
+
// never execute multiple gracefullExit simultaneously
|
|
329
|
+
// this can lead to loss of some apps in dump file
|
|
330
|
+
if (this.isExiting) return
|
|
331
|
+
|
|
332
|
+
this.isExiting = true
|
|
333
|
+
|
|
334
|
+
God.bus.emit('zm2:kill', {
|
|
335
|
+
status : 'killed',
|
|
336
|
+
msg : 'zm2 has been killed by SIGNAL'
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
console.log('zm2 has been killed by signal, dumping process list before exit...');
|
|
340
|
+
|
|
341
|
+
if (God.system_infos_proc !== null)
|
|
342
|
+
God.system_infos_proc.kill()
|
|
343
|
+
|
|
344
|
+
God.dumpProcessList(function() {
|
|
345
|
+
|
|
346
|
+
var processes = God.getFormatedProcesses();
|
|
347
|
+
|
|
348
|
+
eachLimit(processes, 1, function(proc, next) {
|
|
349
|
+
console.log('Deleting process %s', proc.pm2_env.pm_id);
|
|
350
|
+
God.deleteProcessId(proc.pm2_env.pm_id, function() {
|
|
351
|
+
return next();
|
|
352
|
+
});
|
|
353
|
+
}, function(err) {
|
|
354
|
+
try {
|
|
355
|
+
fs.unlinkSync(that.pid_path);
|
|
356
|
+
} catch(e) {}
|
|
357
|
+
setTimeout(function() {
|
|
358
|
+
that.isExiting = false
|
|
359
|
+
console.log('Exited peacefully');
|
|
360
|
+
process.exit(cst.SUCCESS_EXIT);
|
|
361
|
+
}, 2);
|
|
362
|
+
});
|
|
363
|
+
});
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
Daemon.prototype.startLogic = function() {
|
|
367
|
+
var that = this;
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Action treatment specifics
|
|
371
|
+
* Attach actions to pm2_env.axm_actions variables (name + options)
|
|
372
|
+
*/
|
|
373
|
+
God.bus.on('axm:action', function axmActions(msg) {
|
|
374
|
+
var pm2_env = msg.process;
|
|
375
|
+
var exists = false;
|
|
376
|
+
var axm_action = msg.data;
|
|
377
|
+
|
|
378
|
+
if (!pm2_env || !God.clusters_db[pm2_env.pm_id])
|
|
379
|
+
return console.error('AXM ACTION Unknown id %s', pm2_env.pm_id);
|
|
380
|
+
|
|
381
|
+
if (!God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions)
|
|
382
|
+
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions = [];
|
|
383
|
+
|
|
384
|
+
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions.forEach(function(actions) {
|
|
385
|
+
if (actions.action_name == axm_action.action_name)
|
|
386
|
+
exists = true;
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
if (exists === false) {
|
|
390
|
+
debug('Adding action', axm_action);
|
|
391
|
+
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions.push(axm_action);
|
|
392
|
+
}
|
|
393
|
+
msg = null;
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Configure module
|
|
398
|
+
*/
|
|
399
|
+
God.bus.on('axm:option:configuration', function axmMonitor(msg) {
|
|
400
|
+
if (!msg.process)
|
|
401
|
+
return console.error('[axm:option:configuration] no process defined');
|
|
402
|
+
|
|
403
|
+
if (!God.clusters_db[msg.process.pm_id])
|
|
404
|
+
return console.error('[axm:option:configuration] Unknown id %s', msg.process.pm_id);
|
|
405
|
+
|
|
406
|
+
try {
|
|
407
|
+
// Application Name nverride
|
|
408
|
+
if (msg.data.name)
|
|
409
|
+
God.clusters_db[msg.process.pm_id].pm2_env.name = msg.data.name;
|
|
410
|
+
|
|
411
|
+
Object.keys(msg.data).forEach(function(conf_key) {
|
|
412
|
+
God.clusters_db[msg.process.pm_id].pm2_env.axm_options[conf_key] = Utility.clone(msg.data[conf_key]);
|
|
413
|
+
});
|
|
414
|
+
} catch(e) {
|
|
415
|
+
console.error(e.stack || e);
|
|
416
|
+
}
|
|
417
|
+
msg = null;
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
/**
|
|
421
|
+
* Process monitoring data (probes)
|
|
422
|
+
*/
|
|
423
|
+
God.bus.on('axm:monitor', function axmMonitor(msg) {
|
|
424
|
+
if (!msg.process)
|
|
425
|
+
return console.error('[axm:monitor] no process defined');
|
|
426
|
+
|
|
427
|
+
if (!msg.process || !God.clusters_db[msg.process.pm_id])
|
|
428
|
+
return console.error('AXM MONITOR Unknown id %s', msg.process.pm_id);
|
|
429
|
+
|
|
430
|
+
Object.assign(God.clusters_db[msg.process.pm_id].pm2_env.axm_monitor, Utility.clone(msg.data));
|
|
431
|
+
msg = null;
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
/**
|
|
435
|
+
* Broadcast messages
|
|
436
|
+
*/
|
|
437
|
+
God.bus.onAny(function(event, data_v) {
|
|
438
|
+
if (['axm:action',
|
|
439
|
+
'axm:monitor',
|
|
440
|
+
'axm:option:setPID',
|
|
441
|
+
'axm:option:configuration'].indexOf(event) > -1) {
|
|
442
|
+
data_v = null;
|
|
443
|
+
return false;
|
|
444
|
+
}
|
|
445
|
+
that.pub.emit(event, Utility.clone(data_v));
|
|
446
|
+
data_v = null;
|
|
447
|
+
});
|
|
448
|
+
};
|
|
449
|
+
|
|
450
|
+
if (require.main === module) {
|
|
451
|
+
process.title = process.env.ZM2_DAEMON_TITLE || 'ZM2 v' + pkg.version + ': God Daemon (' + process.env.ZM2_HOME + ')';
|
|
452
|
+
|
|
453
|
+
var daemon = new Daemon();
|
|
454
|
+
|
|
455
|
+
daemon.start();
|
|
456
|
+
}
|
package/lib/Event.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
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
|
+
|
|
7
|
+
var Utility = require('./Utility.js');
|
|
8
|
+
|
|
9
|
+
module.exports = function(God) {
|
|
10
|
+
|
|
11
|
+
God.notify = function(action_name, data, manually) {
|
|
12
|
+
God.bus.emit('process:event', {
|
|
13
|
+
event : action_name,
|
|
14
|
+
manually : typeof(manually) == 'undefined' ? false : true,
|
|
15
|
+
process : Utility.formatCLU(data),
|
|
16
|
+
at : Utility.getDate()
|
|
17
|
+
});
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
God.notifyByProcessId = function(opts, cb) {
|
|
21
|
+
if (typeof(opts.id) === 'undefined') { return cb(new Error('process id missing')); }
|
|
22
|
+
var proc = God.clusters_db[opts.id];
|
|
23
|
+
if (!proc) { return cb(new Error('process id doesnt exists')); }
|
|
24
|
+
|
|
25
|
+
God.bus.emit('process:event', {
|
|
26
|
+
event : opts.action_name,
|
|
27
|
+
manually : typeof(opts.manually) == 'undefined' ? false : true,
|
|
28
|
+
process : Utility.formatCLU(proc),
|
|
29
|
+
at : Utility.getDate()
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
process.nextTick(function() {
|
|
33
|
+
return cb ? cb(null) : false;
|
|
34
|
+
});
|
|
35
|
+
return false;
|
|
36
|
+
};
|
|
37
|
+
};
|