@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/Client.js
ADDED
|
@@ -0,0 +1,776 @@
|
|
|
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:client');
|
|
8
|
+
var Common = require('./Common.js');
|
|
9
|
+
var KMDaemon = require('@pm2/agent/src/InteractorClient');
|
|
10
|
+
var rpc = require('pm2-axon-rpc');
|
|
11
|
+
var forEach = require('async/forEach');
|
|
12
|
+
var axon = require('pm2-axon');
|
|
13
|
+
var util = require('util');
|
|
14
|
+
var fs = require('fs');
|
|
15
|
+
var path = require('path');
|
|
16
|
+
var pkg = require('../package.json');
|
|
17
|
+
var which = require('./tools/which.js');
|
|
18
|
+
|
|
19
|
+
function noop() {}
|
|
20
|
+
|
|
21
|
+
var Client = module.exports = function(opts) {
|
|
22
|
+
if (!opts) opts = {};
|
|
23
|
+
|
|
24
|
+
if (!opts.conf)
|
|
25
|
+
this.conf = require('../constants.js');
|
|
26
|
+
else {
|
|
27
|
+
this.conf = opts.conf;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.daemon_mode = typeof(opts.daemon_mode) === 'undefined' ? true : opts.daemon_mode;
|
|
31
|
+
this.pm2_home = this.conf.PM2_ROOT_PATH;
|
|
32
|
+
this.secret_key = opts.secret_key;
|
|
33
|
+
this.public_key = opts.public_key;
|
|
34
|
+
this.machine_name = opts.machine_name;
|
|
35
|
+
|
|
36
|
+
// Create all folders and files needed
|
|
37
|
+
// Client depends to that to interact with ZM2 properly
|
|
38
|
+
this.initFileStructure(this.conf);
|
|
39
|
+
|
|
40
|
+
debug('Using RPC file %s', this.conf.DAEMON_RPC_PORT);
|
|
41
|
+
debug('Using PUB file %s', this.conf.DAEMON_PUB_PORT);
|
|
42
|
+
this.rpc_socket_file = this.conf.DAEMON_RPC_PORT;
|
|
43
|
+
this.pub_socket_file = this.conf.DAEMON_PUB_PORT;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// @breaking change (noDaemonMode has been drop)
|
|
47
|
+
// @todo ret err
|
|
48
|
+
Client.prototype.start = function(cb) {
|
|
49
|
+
var that = this;
|
|
50
|
+
|
|
51
|
+
this.pingDaemon(function(daemonAlive) {
|
|
52
|
+
if (daemonAlive === true)
|
|
53
|
+
return that.launchRPC(function(err, meta) {
|
|
54
|
+
return cb(null, {
|
|
55
|
+
daemon_mode : that.conf.daemon_mode,
|
|
56
|
+
new_pm2_instance : false,
|
|
57
|
+
rpc_socket_file : that.rpc_socket_file,
|
|
58
|
+
pub_socket_file : that.pub_socket_file,
|
|
59
|
+
pm2_home : that.pm2_home
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* No Daemon mode
|
|
65
|
+
*/
|
|
66
|
+
if (that.daemon_mode === false) {
|
|
67
|
+
var Daemon = require('./Daemon.js');
|
|
68
|
+
|
|
69
|
+
var daemon = new Daemon({
|
|
70
|
+
pub_socket_file : that.conf.DAEMON_PUB_PORT,
|
|
71
|
+
rpc_socket_file : that.conf.DAEMON_RPC_PORT,
|
|
72
|
+
pid_file : that.conf.PM2_PID_FILE_PATH,
|
|
73
|
+
ignore_signals : true
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
console.log('Launching in no daemon mode');
|
|
77
|
+
|
|
78
|
+
daemon.innerStart(function() {
|
|
79
|
+
KMDaemon.launchAndInteract(that.conf, {
|
|
80
|
+
machine_name : that.machine_name,
|
|
81
|
+
public_key : that.public_key,
|
|
82
|
+
secret_key : that.secret_key,
|
|
83
|
+
pm2_version : pkg.version
|
|
84
|
+
}, function(err, data, interactor_proc) {
|
|
85
|
+
that.interactor_process = interactor_proc;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
that.launchRPC(function(err, meta) {
|
|
89
|
+
return cb(null, {
|
|
90
|
+
daemon_mode : that.conf.daemon_mode,
|
|
91
|
+
new_pm2_instance : true,
|
|
92
|
+
rpc_socket_file : that.rpc_socket_file,
|
|
93
|
+
pub_socket_file : that.pub_socket_file,
|
|
94
|
+
pm2_home : that.pm2_home
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Daemon mode
|
|
103
|
+
*/
|
|
104
|
+
that.launchDaemon(function(err, child) {
|
|
105
|
+
if (err) {
|
|
106
|
+
Common.printError(err);
|
|
107
|
+
return cb ? cb(err) : process.exit(that.conf.ERROR_EXIT);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (!(process.env.ZM2_DISCRETE_MODE || process.env.PM2_DISCRETE_MODE))
|
|
111
|
+
Common.printOut(that.conf.PREFIX_MSG + 'ZM2 Successfully daemonized');
|
|
112
|
+
|
|
113
|
+
that.launchRPC(function(err, meta) {
|
|
114
|
+
return cb(null, {
|
|
115
|
+
daemon_mode : that.conf.daemon_mode,
|
|
116
|
+
new_pm2_instance : true,
|
|
117
|
+
rpc_socket_file : that.rpc_socket_file,
|
|
118
|
+
pub_socket_file : that.pub_socket_file,
|
|
119
|
+
pm2_home : that.pm2_home
|
|
120
|
+
});
|
|
121
|
+
});
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
// Init file structure of zm2_home
|
|
127
|
+
// This includes
|
|
128
|
+
// - zm2 pid and log path
|
|
129
|
+
// - rpc and pub socket for command execution
|
|
130
|
+
Client.prototype.initFileStructure = function (opts) {
|
|
131
|
+
if (!fs.existsSync(opts.DEFAULT_LOG_PATH)) {
|
|
132
|
+
try {
|
|
133
|
+
require('mkdirp').sync(opts.DEFAULT_LOG_PATH);
|
|
134
|
+
} catch (e) {
|
|
135
|
+
console.error(e.stack || e);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
if (!fs.existsSync(opts.DEFAULT_PID_PATH)) {
|
|
140
|
+
try {
|
|
141
|
+
require('mkdirp').sync(opts.DEFAULT_PID_PATH);
|
|
142
|
+
} catch (e) {
|
|
143
|
+
console.error(e.stack || e);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (!fs.existsSync(opts.PM2_MODULE_CONF_FILE)) {
|
|
148
|
+
try {
|
|
149
|
+
fs.writeFileSync(opts.PM2_MODULE_CONF_FILE, "{}");
|
|
150
|
+
} catch (e) {
|
|
151
|
+
console.error(e.stack || e);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (!fs.existsSync(opts.DEFAULT_MODULE_PATH)) {
|
|
156
|
+
try {
|
|
157
|
+
require('mkdirp').sync(opts.DEFAULT_MODULE_PATH);
|
|
158
|
+
} catch (e) {
|
|
159
|
+
console.error(e.stack || e);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (process.env.ZM2_DISCRETE_MODE || process.env.PM2_DISCRETE_MODE) {
|
|
164
|
+
try {
|
|
165
|
+
fs.writeFileSync(path.join(opts.PM2_HOME, 'touch'), Date.now().toString());
|
|
166
|
+
} catch(e) {
|
|
167
|
+
debug(e.stack || e);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!(process.env.ZM2_PROGRAMMATIC || process.env.PM2_PROGRAMMATIC) && !fs.existsSync(path.join(opts.PM2_HOME, 'touch'))) {
|
|
172
|
+
|
|
173
|
+
var vCheck = require('./VersionCheck.js')
|
|
174
|
+
|
|
175
|
+
vCheck({
|
|
176
|
+
state: 'install',
|
|
177
|
+
version: pkg.version
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
var dt = fs.readFileSync(path.join(__dirname, opts.PM2_BANNER));
|
|
181
|
+
console.log(dt.toString());
|
|
182
|
+
try {
|
|
183
|
+
fs.writeFileSync(path.join(opts.PM2_HOME, 'touch'), Date.now().toString());
|
|
184
|
+
} catch(e) {
|
|
185
|
+
debug(e.stack || e);
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
};
|
|
189
|
+
|
|
190
|
+
Client.prototype.close = function(cb) {
|
|
191
|
+
var that = this;
|
|
192
|
+
|
|
193
|
+
forEach([
|
|
194
|
+
that.disconnectRPC.bind(that),
|
|
195
|
+
that.disconnectBus.bind(that)
|
|
196
|
+
], function(fn, next) {
|
|
197
|
+
fn(next)
|
|
198
|
+
}, cb);
|
|
199
|
+
};
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Launch the Daemon by forking this same file
|
|
203
|
+
* The method Client.remoteWrapper will be called
|
|
204
|
+
*
|
|
205
|
+
* @method launchDaemon
|
|
206
|
+
* @param {Object} opts
|
|
207
|
+
* @param {Object} [opts.interactor=true] allow to disable interaction on launch
|
|
208
|
+
*/
|
|
209
|
+
Client.prototype.launchDaemon = function(opts, cb) {
|
|
210
|
+
if (typeof(opts) == 'function') {
|
|
211
|
+
cb = opts;
|
|
212
|
+
opts = {
|
|
213
|
+
interactor : true
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
var that = this
|
|
218
|
+
var ClientJS = path.resolve(path.dirname(module.filename), 'Daemon.js');
|
|
219
|
+
var node_args = [];
|
|
220
|
+
var out, err;
|
|
221
|
+
|
|
222
|
+
// if (process.env.TRAVIS) {
|
|
223
|
+
// // Redirect ZM2 internal err and out to STDERR STDOUT when running with Travis
|
|
224
|
+
// out = 1;
|
|
225
|
+
// err = 2;
|
|
226
|
+
// }
|
|
227
|
+
// else {
|
|
228
|
+
out = fs.openSync(that.conf.PM2_LOG_FILE_PATH, 'a'),
|
|
229
|
+
err = fs.openSync(that.conf.PM2_LOG_FILE_PATH, 'a');
|
|
230
|
+
//}
|
|
231
|
+
|
|
232
|
+
if (this.conf.LOW_MEMORY_ENVIRONMENT) {
|
|
233
|
+
var os = require('os');
|
|
234
|
+
node_args.push('--gc-global'); // Does full GC (smaller memory footprint)
|
|
235
|
+
node_args.push('--max-old-space-size=' + Math.floor(os.totalmem() / 1024 / 1024));
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Node.js tuning for better performance
|
|
239
|
+
//node_args.push('--expose-gc'); // Allows manual GC in the code
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Add node [arguments] depending on ZM2_NODE_OPTIONS env variable
|
|
243
|
+
*/
|
|
244
|
+
if (process.env.ZM2_NODE_OPTIONS || process.env.PM2_NODE_OPTIONS)
|
|
245
|
+
node_args = node_args.concat((process.env.ZM2_NODE_OPTIONS || process.env.PM2_NODE_OPTIONS).split(' '));
|
|
246
|
+
node_args.push(ClientJS);
|
|
247
|
+
|
|
248
|
+
if (!(process.env.ZM2_DISCRETE_MODE || process.env.PM2_DISCRETE_MODE))
|
|
249
|
+
Common.printOut(that.conf.PREFIX_MSG + 'Spawning ZM2 daemon with zm2_home=' + this.pm2_home);
|
|
250
|
+
|
|
251
|
+
var interpreter = process.execPath;
|
|
252
|
+
|
|
253
|
+
var child = require('child_process').spawn(interpreter, node_args, {
|
|
254
|
+
detached : true,
|
|
255
|
+
cwd : that.conf.cwd || process.cwd(),
|
|
256
|
+
windowsHide: true,
|
|
257
|
+
env : Object.assign({
|
|
258
|
+
'SILENT' : that.conf.DEBUG ? !that.conf.DEBUG : true,
|
|
259
|
+
'PM2_HOME' : that.pm2_home
|
|
260
|
+
}, process.env),
|
|
261
|
+
stdio : [null, out, err, 'ipc']
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
function onError(e) {
|
|
265
|
+
console.error(e.message || e);
|
|
266
|
+
return cb ? cb(e.message || e) : false;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
child.once('error', onError);
|
|
270
|
+
|
|
271
|
+
if (this.conf.IS_BUN === false)
|
|
272
|
+
child.unref();
|
|
273
|
+
|
|
274
|
+
child.once('message', function(msg) {
|
|
275
|
+
debug('ZM2 daemon launched with return message: ', msg);
|
|
276
|
+
child.removeListener('error', onError);
|
|
277
|
+
child.disconnect();
|
|
278
|
+
if (opts && opts.interactor == false)
|
|
279
|
+
return cb(null, child);
|
|
280
|
+
|
|
281
|
+
if (process.env.ZM2_NO_INTERACTION == 'true' || process.env.PM2_NO_INTERACTION == 'true')
|
|
282
|
+
return cb(null, child);
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Here the Keymetrics agent is launched automaticcaly if
|
|
286
|
+
* it has been already configured before (via zm2 link)
|
|
287
|
+
*/
|
|
288
|
+
KMDaemon.launchAndInteract(that.conf, {
|
|
289
|
+
machine_name : that.machine_name,
|
|
290
|
+
public_key : that.public_key,
|
|
291
|
+
secret_key : that.secret_key,
|
|
292
|
+
pm2_version : pkg.version
|
|
293
|
+
}, function(err, data, interactor_proc) {
|
|
294
|
+
that.interactor_process = interactor_proc;
|
|
295
|
+
return cb(null, child);
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Ping the daemon to know if it alive or not
|
|
302
|
+
* @api public
|
|
303
|
+
* @method pingDaemon
|
|
304
|
+
* @param {} cb
|
|
305
|
+
* @return
|
|
306
|
+
*/
|
|
307
|
+
Client.prototype.pingDaemon = function pingDaemon(cb) {
|
|
308
|
+
var req = axon.socket('req');
|
|
309
|
+
var client = new rpc.Client(req);
|
|
310
|
+
var that = this;
|
|
311
|
+
|
|
312
|
+
debug('[PING ZM2] Trying to connect to server');
|
|
313
|
+
|
|
314
|
+
client.sock.once('reconnect attempt', function() {
|
|
315
|
+
client.sock.close();
|
|
316
|
+
debug('Daemon not launched');
|
|
317
|
+
process.nextTick(function() {
|
|
318
|
+
return cb(false);
|
|
319
|
+
});
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
client.sock.once('error', function(e) {
|
|
323
|
+
if (e.code === 'EACCES') {
|
|
324
|
+
fs.stat(that.conf.DAEMON_RPC_PORT, function(e, stats) {
|
|
325
|
+
if (stats.uid === 0) {
|
|
326
|
+
console.error(that.conf.PREFIX_MSG_ERR + 'Permission denied, to give access to current user:');
|
|
327
|
+
console.log('$ sudo chown ' + process.env.USER + ':' + process.env.USER + ' ' + that.conf.DAEMON_RPC_PORT + ' ' + that.conf.DAEMON_PUB_PORT);
|
|
328
|
+
}
|
|
329
|
+
else
|
|
330
|
+
console.error(that.conf.PREFIX_MSG_ERR + 'Permission denied, check permissions on ' + that.conf.DAEMON_RPC_PORT);
|
|
331
|
+
|
|
332
|
+
process.exit(1);
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
else
|
|
336
|
+
console.error(e.message || e);
|
|
337
|
+
});
|
|
338
|
+
|
|
339
|
+
client.sock.once('connect', function() {
|
|
340
|
+
client.sock.once('close', function() {
|
|
341
|
+
return cb(true);
|
|
342
|
+
});
|
|
343
|
+
client.sock.close();
|
|
344
|
+
debug('Daemon alive');
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
req.connect(this.rpc_socket_file);
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Methods to interact with the Daemon via RPC
|
|
352
|
+
* This method wait to be connected to the Daemon
|
|
353
|
+
* Once he's connected it trigger the command parsing (on ./bin/zm2 file, at the end)
|
|
354
|
+
* @method launchRPC
|
|
355
|
+
* @params {function} [cb]
|
|
356
|
+
* @return
|
|
357
|
+
*/
|
|
358
|
+
Client.prototype.launchRPC = function launchRPC(cb) {
|
|
359
|
+
var self = this;
|
|
360
|
+
debug('Launching RPC client on socket file %s', this.rpc_socket_file);
|
|
361
|
+
var req = axon.socket('req');
|
|
362
|
+
this.client = new rpc.Client(req);
|
|
363
|
+
|
|
364
|
+
var connectHandler = function() {
|
|
365
|
+
self.client.sock.removeListener('error', errorHandler);
|
|
366
|
+
debug('RPC Connected to Daemon');
|
|
367
|
+
if (cb) {
|
|
368
|
+
setTimeout(function() {
|
|
369
|
+
cb(null);
|
|
370
|
+
}, 4);
|
|
371
|
+
}
|
|
372
|
+
};
|
|
373
|
+
|
|
374
|
+
var errorHandler = function(e) {
|
|
375
|
+
self.client.sock.removeListener('connect', connectHandler);
|
|
376
|
+
if (cb) {
|
|
377
|
+
return cb(e);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
this.client.sock.once('connect', connectHandler);
|
|
382
|
+
this.client.sock.once('error', errorHandler);
|
|
383
|
+
this.client_sock = req.connect(this.rpc_socket_file);
|
|
384
|
+
};
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Methods to close the RPC connection
|
|
388
|
+
* @callback cb
|
|
389
|
+
*/
|
|
390
|
+
Client.prototype.disconnectRPC = function disconnectRPC(cb) {
|
|
391
|
+
var that = this;
|
|
392
|
+
if (!cb) cb = noop;
|
|
393
|
+
|
|
394
|
+
if (!this.client_sock || !this.client_sock.close) {
|
|
395
|
+
this.client = null;
|
|
396
|
+
return process.nextTick(function() {
|
|
397
|
+
cb(new Error('SUB connection to ZM2 is not launched'));
|
|
398
|
+
});
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
if (this.client_sock.connected === false ||
|
|
402
|
+
this.client_sock.closing === true) {
|
|
403
|
+
this.client = null;
|
|
404
|
+
return process.nextTick(function() {
|
|
405
|
+
cb(new Error('RPC already being closed'));
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
try {
|
|
410
|
+
var timer;
|
|
411
|
+
|
|
412
|
+
that.client_sock.once('close', function() {
|
|
413
|
+
clearTimeout(timer);
|
|
414
|
+
that.client = null;
|
|
415
|
+
debug('ZM2 RPC cleanly closed');
|
|
416
|
+
return cb(null, { msg : 'RPC Successfully closed' });
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
timer = setTimeout(function() {
|
|
420
|
+
if (that.client_sock.destroy)
|
|
421
|
+
that.client_sock.destroy();
|
|
422
|
+
that.client = null;
|
|
423
|
+
return cb(null, { msg : 'RPC Successfully closed via timeout' });
|
|
424
|
+
}, 200);
|
|
425
|
+
|
|
426
|
+
that.client_sock.close();
|
|
427
|
+
} catch(e) {
|
|
428
|
+
debug('Error while disconnecting RPC ZM2', e.stack || e);
|
|
429
|
+
return cb(e);
|
|
430
|
+
}
|
|
431
|
+
return false;
|
|
432
|
+
};
|
|
433
|
+
|
|
434
|
+
Client.prototype.launchBus = function launchEventSystem(cb) {
|
|
435
|
+
var self = this;
|
|
436
|
+
this.sub = axon.socket('sub-emitter');
|
|
437
|
+
this.sub_sock = this.sub.connect(this.pub_socket_file);
|
|
438
|
+
|
|
439
|
+
this.sub_sock.once('connect', function() {
|
|
440
|
+
return cb(null, self.sub, self.sub_sock);
|
|
441
|
+
});
|
|
442
|
+
};
|
|
443
|
+
|
|
444
|
+
Client.prototype.disconnectBus = function disconnectBus(cb) {
|
|
445
|
+
if (!cb) cb = noop;
|
|
446
|
+
|
|
447
|
+
var that = this;
|
|
448
|
+
|
|
449
|
+
if (!this.sub_sock || !this.sub_sock.close) {
|
|
450
|
+
that.sub = null;
|
|
451
|
+
return process.nextTick(function() {
|
|
452
|
+
cb(null, { msg : 'bus was not connected'});
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
if (this.sub_sock.connected === false ||
|
|
457
|
+
this.sub_sock.closing === true) {
|
|
458
|
+
that.sub = null;
|
|
459
|
+
return process.nextTick(function() {
|
|
460
|
+
cb(new Error('SUB connection is already being closed'));
|
|
461
|
+
});
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
try {
|
|
465
|
+
var timer;
|
|
466
|
+
|
|
467
|
+
that.sub_sock.once('close', function() {
|
|
468
|
+
that.sub = null;
|
|
469
|
+
clearTimeout(timer);
|
|
470
|
+
debug('ZM2 PUB cleanly closed');
|
|
471
|
+
return cb();
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
timer = setTimeout(function() {
|
|
475
|
+
if (Client.sub_sock.destroy)
|
|
476
|
+
that.sub_sock.destroy();
|
|
477
|
+
return cb();
|
|
478
|
+
}, 200);
|
|
479
|
+
|
|
480
|
+
this.sub_sock.close();
|
|
481
|
+
} catch(e) {
|
|
482
|
+
return cb(e);
|
|
483
|
+
}
|
|
484
|
+
};
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Description
|
|
488
|
+
* @method gestExposedMethods
|
|
489
|
+
* @param {} cb
|
|
490
|
+
* @return
|
|
491
|
+
*/
|
|
492
|
+
Client.prototype.getExposedMethods = function getExposedMethods(cb) {
|
|
493
|
+
this.client.methods(cb);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
/**
|
|
497
|
+
* Description
|
|
498
|
+
* @method executeRemote
|
|
499
|
+
* @param {} method
|
|
500
|
+
* @param {} env
|
|
501
|
+
* @param {} fn
|
|
502
|
+
* @return
|
|
503
|
+
*/
|
|
504
|
+
Client.prototype.executeRemote = function executeRemote(method, app_conf, fn) {
|
|
505
|
+
var self = this;
|
|
506
|
+
|
|
507
|
+
// stop watch on stop | env is the process id
|
|
508
|
+
if (method.indexOf('stop') !== -1) {
|
|
509
|
+
this.stopWatch(method, app_conf);
|
|
510
|
+
}
|
|
511
|
+
// stop watching when process is deleted
|
|
512
|
+
else if (method.indexOf('delete') !== -1) {
|
|
513
|
+
this.stopWatch(method, app_conf);
|
|
514
|
+
}
|
|
515
|
+
// stop everything on kill
|
|
516
|
+
else if (method.indexOf('kill') !== -1) {
|
|
517
|
+
this.stopWatch('deleteAll', app_conf);
|
|
518
|
+
}
|
|
519
|
+
else if (method.indexOf('restartProcessId') !== -1 && process.argv.indexOf('--watch') > -1) {
|
|
520
|
+
delete app_conf.env.current_conf.watch;
|
|
521
|
+
this.toggleWatch(method, app_conf);
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
if (!this.client || !this.client.call) {
|
|
525
|
+
this.start(function(error) {
|
|
526
|
+
if (error) {
|
|
527
|
+
if (fn)
|
|
528
|
+
return fn(error);
|
|
529
|
+
console.error(error);
|
|
530
|
+
return process.exit(0);
|
|
531
|
+
}
|
|
532
|
+
if (self.client) {
|
|
533
|
+
return self.client.call(method, app_conf, fn);
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
return false;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
debug('Calling daemon method zm2:%s on rpc socket:%s', method, this.rpc_socket_file);
|
|
540
|
+
return this.client.call(method, app_conf, fn);
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
Client.prototype.notifyGod = function(action_name, id, cb) {
|
|
544
|
+
this.executeRemote('notifyByProcessId', {
|
|
545
|
+
id : id,
|
|
546
|
+
action_name : action_name,
|
|
547
|
+
manually : true
|
|
548
|
+
}, function() {
|
|
549
|
+
debug('God notified');
|
|
550
|
+
return cb ? cb() : false;
|
|
551
|
+
});
|
|
552
|
+
};
|
|
553
|
+
|
|
554
|
+
Client.prototype.killDaemon = function killDaemon(fn) {
|
|
555
|
+
var timeout;
|
|
556
|
+
var that = this;
|
|
557
|
+
|
|
558
|
+
function quit() {
|
|
559
|
+
that.close(function() {
|
|
560
|
+
return fn ? fn(null, {success:true}) : false;
|
|
561
|
+
});
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
// under unix, we listen for signal (that is send by daemon to notify us that its shuting down)
|
|
565
|
+
if (process.platform !== 'win32' && process.platform !== 'win64') {
|
|
566
|
+
process.once('SIGQUIT', function() {
|
|
567
|
+
debug('Received SIGQUIT from zm2 daemon');
|
|
568
|
+
clearTimeout(timeout);
|
|
569
|
+
quit();
|
|
570
|
+
});
|
|
571
|
+
}
|
|
572
|
+
else {
|
|
573
|
+
// if under windows, try to ping the daemon to see if it still here
|
|
574
|
+
setTimeout(function() {
|
|
575
|
+
that.pingDaemon(function(alive) {
|
|
576
|
+
if (!alive) {
|
|
577
|
+
clearTimeout(timeout);
|
|
578
|
+
return quit();
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
}, 250)
|
|
582
|
+
}
|
|
583
|
+
|
|
584
|
+
timeout = setTimeout(function() {
|
|
585
|
+
quit();
|
|
586
|
+
}, 3000);
|
|
587
|
+
|
|
588
|
+
// Kill daemon
|
|
589
|
+
this.executeRemote('killMe', {pid : process.pid});
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
|
|
593
|
+
/**
|
|
594
|
+
* Description
|
|
595
|
+
* @method toggleWatch
|
|
596
|
+
* @param {String} zm2 method name
|
|
597
|
+
* @param {Object} application environment, should include id
|
|
598
|
+
* @param {Function} callback
|
|
599
|
+
*/
|
|
600
|
+
Client.prototype.toggleWatch = function toggleWatch(method, env, fn) {
|
|
601
|
+
debug('Calling toggleWatch');
|
|
602
|
+
this.client.call('toggleWatch', method, env, function() {
|
|
603
|
+
return fn ? fn() : false;
|
|
604
|
+
});
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
/**
|
|
608
|
+
* Description
|
|
609
|
+
* @method startWatch
|
|
610
|
+
* @param {String} zm2 method name
|
|
611
|
+
* @param {Object} application environment, should include id
|
|
612
|
+
* @param {Function} callback
|
|
613
|
+
*/
|
|
614
|
+
Client.prototype.startWatch = function restartWatch(method, env, fn) {
|
|
615
|
+
debug('Calling startWatch');
|
|
616
|
+
this.client.call('startWatch', method, env, function() {
|
|
617
|
+
return fn ? fn() : false;
|
|
618
|
+
});
|
|
619
|
+
};
|
|
620
|
+
|
|
621
|
+
/**
|
|
622
|
+
* Description
|
|
623
|
+
* @method stopWatch
|
|
624
|
+
* @param {String} zm2 method name
|
|
625
|
+
* @param {Object} application environment, should include id
|
|
626
|
+
* @param {Function} callback
|
|
627
|
+
*/
|
|
628
|
+
Client.prototype.stopWatch = function stopWatch(method, env, fn) {
|
|
629
|
+
debug('Calling stopWatch');
|
|
630
|
+
this.client.call('stopWatch', method, env, function() {
|
|
631
|
+
return fn ? fn() : false;
|
|
632
|
+
});
|
|
633
|
+
};
|
|
634
|
+
|
|
635
|
+
Client.prototype.getAllProcess = function(cb) {
|
|
636
|
+
var found_proc = [];
|
|
637
|
+
|
|
638
|
+
this.executeRemote('getMonitorData', {}, function(err, procs) {
|
|
639
|
+
if (err) {
|
|
640
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
641
|
+
return cb(err);
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
return cb(null, procs);
|
|
645
|
+
});
|
|
646
|
+
};
|
|
647
|
+
|
|
648
|
+
Client.prototype.getAllProcessId = function(cb) {
|
|
649
|
+
var found_proc = [];
|
|
650
|
+
|
|
651
|
+
this.executeRemote('getMonitorData', {}, function(err, procs) {
|
|
652
|
+
if (err) {
|
|
653
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
654
|
+
return cb(err);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
return cb(null, procs.map(proc => proc.pm_id));
|
|
658
|
+
});
|
|
659
|
+
};
|
|
660
|
+
|
|
661
|
+
Client.prototype.getAllProcessIdWithoutModules = function(cb) {
|
|
662
|
+
var found_proc = [];
|
|
663
|
+
|
|
664
|
+
this.executeRemote('getMonitorData', {}, function(err, procs) {
|
|
665
|
+
if (err) {
|
|
666
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
667
|
+
return cb(err);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
var proc_ids = procs
|
|
671
|
+
.filter(proc => !proc.pm2_env.pmx_module)
|
|
672
|
+
.map(proc => proc.pm_id)
|
|
673
|
+
|
|
674
|
+
return cb(null, proc_ids);
|
|
675
|
+
});
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
Client.prototype.getProcessIdByName = function(name, force_all, cb) {
|
|
679
|
+
var found_proc = [];
|
|
680
|
+
var full_details = {};
|
|
681
|
+
|
|
682
|
+
if (typeof(cb) === 'undefined') {
|
|
683
|
+
cb = force_all;
|
|
684
|
+
force_all = false;
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
if (typeof(name) == 'number')
|
|
688
|
+
name = name.toString();
|
|
689
|
+
|
|
690
|
+
this.executeRemote('getMonitorData', {}, function(err, list) {
|
|
691
|
+
if (err) {
|
|
692
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
693
|
+
return cb(err);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
list.forEach(function(proc) {
|
|
697
|
+
if (proc.pm2_env.name == name || proc.pm2_env.pm_exec_path == path.resolve(name)) {
|
|
698
|
+
found_proc.push(proc.pm_id);
|
|
699
|
+
full_details[proc.pm_id] = proc;
|
|
700
|
+
}
|
|
701
|
+
});
|
|
702
|
+
|
|
703
|
+
return cb(null, found_proc, full_details);
|
|
704
|
+
});
|
|
705
|
+
};
|
|
706
|
+
|
|
707
|
+
Client.prototype.getProcessIdsByNamespace = function(namespace, force_all, cb) {
|
|
708
|
+
var found_proc = [];
|
|
709
|
+
var full_details = {};
|
|
710
|
+
|
|
711
|
+
if (typeof(cb) === 'undefined') {
|
|
712
|
+
cb = force_all;
|
|
713
|
+
force_all = false;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
if (typeof(namespace) == 'number')
|
|
717
|
+
namespace = namespace.toString();
|
|
718
|
+
|
|
719
|
+
this.executeRemote('getMonitorData', {}, function(err, list) {
|
|
720
|
+
if (err) {
|
|
721
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
722
|
+
return cb(err);
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
list.forEach(function(proc) {
|
|
726
|
+
if (proc.pm2_env.namespace == namespace) {
|
|
727
|
+
found_proc.push(proc.pm_id);
|
|
728
|
+
full_details[proc.pm_id] = proc;
|
|
729
|
+
}
|
|
730
|
+
});
|
|
731
|
+
|
|
732
|
+
return cb(null, found_proc, full_details);
|
|
733
|
+
});
|
|
734
|
+
};
|
|
735
|
+
|
|
736
|
+
Client.prototype.getProcessByName = function(name, cb) {
|
|
737
|
+
var found_proc = [];
|
|
738
|
+
|
|
739
|
+
this.executeRemote('getMonitorData', {}, function(err, list) {
|
|
740
|
+
if (err) {
|
|
741
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
742
|
+
return cb(err);
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
list.forEach(function(proc) {
|
|
746
|
+
if (proc.pm2_env.name == name ||
|
|
747
|
+
proc.pm2_env.pm_exec_path == path.resolve(name)) {
|
|
748
|
+
found_proc.push(proc);
|
|
749
|
+
}
|
|
750
|
+
});
|
|
751
|
+
|
|
752
|
+
return cb(null, found_proc);
|
|
753
|
+
});
|
|
754
|
+
};
|
|
755
|
+
|
|
756
|
+
Client.prototype.getProcessByNameOrId = function (nameOrId, cb) {
|
|
757
|
+
var foundProc = [];
|
|
758
|
+
|
|
759
|
+
this.executeRemote('getMonitorData', {}, function (err, list) {
|
|
760
|
+
if (err) {
|
|
761
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
762
|
+
return cb(err);
|
|
763
|
+
}
|
|
764
|
+
|
|
765
|
+
list.forEach(function (proc) {
|
|
766
|
+
if (proc.pm2_env.name === nameOrId ||
|
|
767
|
+
proc.pm2_env.pm_exec_path === path.resolve(nameOrId) ||
|
|
768
|
+
proc.pid === parseInt(nameOrId) ||
|
|
769
|
+
proc.pm2_env.pm_id === parseInt(nameOrId)) {
|
|
770
|
+
foundProc.push(proc);
|
|
771
|
+
}
|
|
772
|
+
});
|
|
773
|
+
|
|
774
|
+
return cb(null, foundProc);
|
|
775
|
+
});
|
|
776
|
+
};
|