@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,629 @@
|
|
|
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
|
+
var chalk = require('ansis');
|
|
7
|
+
var path = require('path');
|
|
8
|
+
var fs = require('fs');
|
|
9
|
+
var forEachLimit = require('async/forEachLimit');
|
|
10
|
+
var eachLimit = require('async/eachLimit');
|
|
11
|
+
var Common = require('../Common.js');
|
|
12
|
+
var cst = require('../../constants.js');
|
|
13
|
+
var util = require('util');
|
|
14
|
+
var tmpPath = require('os').tmpdir;
|
|
15
|
+
var which = require('../tools/which.js');
|
|
16
|
+
var sexec = require('../tools/sexec')
|
|
17
|
+
module.exports = function(CLI) {
|
|
18
|
+
/**
|
|
19
|
+
* If command is launched without root right
|
|
20
|
+
* Display helper
|
|
21
|
+
*/
|
|
22
|
+
function isNotRoot(startup_mode, platform, opts, cb) {
|
|
23
|
+
Common.printOut(`${cst.PREFIX_MSG}To ${startup_mode} the Startup Script, copy/paste the following command:`);
|
|
24
|
+
|
|
25
|
+
let pm2_bin_path = require.main.filename
|
|
26
|
+
|
|
27
|
+
if (pm2_bin_path.includes('/lib/binaries/CLI.js') === true) {
|
|
28
|
+
pm2_bin_path = pm2_bin_path.replace('/lib/binaries/CLI.js', '/bin/zm2')
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (opts.user) {
|
|
32
|
+
console.log('sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' zm2 ' + opts.args[1].name() + ' ' + platform + ' -u ' + opts.user + ' --hp ' + process.env.HOME);
|
|
33
|
+
return cb(new Error('You have to run this with elevated rights'));
|
|
34
|
+
}
|
|
35
|
+
return sexec('whoami', {silent: true}, function(err, stdout, stderr) {
|
|
36
|
+
console.log('sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' ' + pm2_bin_path + ' ' + opts.args[1].name() + ' ' + platform + ' -u ' + stdout.trim() + ' --hp ' + process.env.HOME);
|
|
37
|
+
return cb(new Error('You have to run this with elevated rights'));
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Detect running init system
|
|
43
|
+
*/
|
|
44
|
+
function detectInitSystem() {
|
|
45
|
+
var hash_map = {
|
|
46
|
+
'systemctl' : 'systemd',
|
|
47
|
+
'update-rc.d': 'upstart',
|
|
48
|
+
'chkconfig' : 'systemv',
|
|
49
|
+
'rc-update' : 'openrc',
|
|
50
|
+
'launchctl' : 'launchd',
|
|
51
|
+
'sysrc' : 'rcd',
|
|
52
|
+
'rcctl' : 'rcd-openbsd',
|
|
53
|
+
'svcadm' : 'smf'
|
|
54
|
+
};
|
|
55
|
+
var init_systems = Object.keys(hash_map);
|
|
56
|
+
|
|
57
|
+
for (var i = 0; i < init_systems.length; i++) {
|
|
58
|
+
if (which(init_systems[i]) != null) {
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (i >= init_systems.length) {
|
|
64
|
+
Common.printError(cst.PREFIX_MSG_ERR + 'Init system not found');
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
Common.printOut(cst.PREFIX_MSG + 'Init System found: ' + chalk.bold(hash_map[init_systems[i]]));
|
|
68
|
+
return hash_map[init_systems[i]];
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
CLI.prototype.uninstallStartup = function(platform, opts, cb) {
|
|
72
|
+
var commands;
|
|
73
|
+
var that = this;
|
|
74
|
+
var actual_platform = detectInitSystem();
|
|
75
|
+
var user = opts.user || process.env.USER || process.env.LOGNAME; // Use LOGNAME on Solaris-like systems
|
|
76
|
+
var service_name = (opts.serviceName || 'zm2-' + user);
|
|
77
|
+
var openrc_service_name = 'zm2';
|
|
78
|
+
var launchd_service_name = (opts.serviceName || 'zm2.' + user);
|
|
79
|
+
|
|
80
|
+
if (!platform)
|
|
81
|
+
platform = actual_platform;
|
|
82
|
+
else if (actual_platform && actual_platform !== platform) {
|
|
83
|
+
Common.printOut('-----------------------------------------------------------')
|
|
84
|
+
Common.printOut(' ZM2 detected ' + actual_platform + ' but you precised ' + platform)
|
|
85
|
+
Common.printOut(' Please verify that your choice is indeed your init system')
|
|
86
|
+
Common.printOut(' If you arent sure, just run : zm2 startup')
|
|
87
|
+
Common.printOut('-----------------------------------------------------------')
|
|
88
|
+
}
|
|
89
|
+
if (platform === null)
|
|
90
|
+
throw new Error('Init system not found')
|
|
91
|
+
|
|
92
|
+
if (!cb) {
|
|
93
|
+
cb = function(err, data) {
|
|
94
|
+
if (err)
|
|
95
|
+
return that.exitCli(cst.ERROR_EXIT);
|
|
96
|
+
return that.exitCli(cst.SUCCESS_EXIT);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
if (process.getuid() != 0) {
|
|
101
|
+
return isNotRoot('unsetup', platform, opts, cb);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
if (fs.existsSync('/etc/init.d/zm2-init.sh')) {
|
|
105
|
+
platform = 'oldsystem';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
switch(platform) {
|
|
109
|
+
case 'systemd':
|
|
110
|
+
commands = [
|
|
111
|
+
'systemctl stop ' + service_name,
|
|
112
|
+
'systemctl disable ' + service_name,
|
|
113
|
+
'rm /etc/systemd/system/' + service_name + '.service'
|
|
114
|
+
];
|
|
115
|
+
break;
|
|
116
|
+
case 'systemv':
|
|
117
|
+
commands = [
|
|
118
|
+
'chkconfig ' + service_name + ' off',
|
|
119
|
+
'rm /etc/init.d/' + service_name
|
|
120
|
+
];
|
|
121
|
+
break;
|
|
122
|
+
case 'oldsystem':
|
|
123
|
+
Common.printOut(cst.PREFIX_MSG + 'Disabling and deleting old startup system');
|
|
124
|
+
commands = [
|
|
125
|
+
'update-rc.d zm2-init.sh disable',
|
|
126
|
+
'update-rc.d -f zm2-init.sh remove',
|
|
127
|
+
'rm /etc/init.d/zm2-init.sh'
|
|
128
|
+
];
|
|
129
|
+
break;
|
|
130
|
+
case 'openrc':
|
|
131
|
+
service_name = openrc_service_name;
|
|
132
|
+
commands = [
|
|
133
|
+
'/etc/init.d/' + service_name + ' stop',
|
|
134
|
+
'rc-update delete ' + service_name + ' default',
|
|
135
|
+
'rm /etc/init.d/' + service_name
|
|
136
|
+
];
|
|
137
|
+
break;
|
|
138
|
+
case 'upstart':
|
|
139
|
+
commands = [
|
|
140
|
+
'update-rc.d ' + service_name + ' disable',
|
|
141
|
+
'update-rc.d -f ' + service_name + ' remove',
|
|
142
|
+
'rm /etc/init.d/' + service_name
|
|
143
|
+
];
|
|
144
|
+
break;
|
|
145
|
+
case 'launchd':
|
|
146
|
+
var destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist');
|
|
147
|
+
commands = [
|
|
148
|
+
'launchctl remove ' + launchd_service_name + ' || true',
|
|
149
|
+
'rm ' + destination
|
|
150
|
+
];
|
|
151
|
+
break;
|
|
152
|
+
case 'rcd':
|
|
153
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
154
|
+
commands = [
|
|
155
|
+
'/usr/local/etc/rc.d/' + service_name + ' stop',
|
|
156
|
+
'sysrc -x ' + service_name + '_enable',
|
|
157
|
+
'rm /usr/local/etc/rc.d/' + service_name
|
|
158
|
+
];
|
|
159
|
+
break;
|
|
160
|
+
case 'rcd-openbsd':
|
|
161
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
162
|
+
var destination = path.join('/etc/rc.d', service_name);
|
|
163
|
+
commands = [
|
|
164
|
+
'rcctl stop ' + service_name,
|
|
165
|
+
'rcctl disable ' + service_name,
|
|
166
|
+
'rm ' + destination
|
|
167
|
+
];
|
|
168
|
+
break;
|
|
169
|
+
case 'smf':
|
|
170
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
171
|
+
commands = [
|
|
172
|
+
'svcadm disable ' + service_name,
|
|
173
|
+
'svccfg delete -f ' + service_name
|
|
174
|
+
]
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
sexec(commands.join('&& '), function(code, stdout, stderr) {
|
|
178
|
+
Common.printOut(stdout);
|
|
179
|
+
Common.printOut(stderr);
|
|
180
|
+
if (code == 0) {
|
|
181
|
+
Common.printOut(cst.PREFIX_MSG + chalk.bold('Init file disabled.'));
|
|
182
|
+
} else {
|
|
183
|
+
Common.printOut(cst.ERROR_MSG + chalk.bold('Return code : ' + code));
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
cb(null, {
|
|
187
|
+
commands : commands,
|
|
188
|
+
platform : platform
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
/**
|
|
194
|
+
* Startup script generation
|
|
195
|
+
* @method startup
|
|
196
|
+
* @param {string} platform type (centos|redhat|amazon|gentoo|systemd|smf)
|
|
197
|
+
*/
|
|
198
|
+
CLI.prototype.startup = function(platform, opts, cb) {
|
|
199
|
+
var that = this;
|
|
200
|
+
var actual_platform = detectInitSystem();
|
|
201
|
+
var user = (opts.user || process.env.USER || process.env.LOGNAME); // Use LOGNAME on Solaris-like systems
|
|
202
|
+
var service_name = (opts.serviceName || 'zm2-' + user);
|
|
203
|
+
var openrc_service_name = 'zm2';
|
|
204
|
+
var launchd_service_name = (opts.serviceName || 'zm2.' + user);
|
|
205
|
+
|
|
206
|
+
if (!platform)
|
|
207
|
+
platform = actual_platform;
|
|
208
|
+
else if (actual_platform && actual_platform !== platform) {
|
|
209
|
+
Common.printOut('-----------------------------------------------------------')
|
|
210
|
+
Common.printOut(' ZM2 detected ' + actual_platform + ' but you precised ' + platform)
|
|
211
|
+
Common.printOut(' Please verify that your choice is indeed your init system')
|
|
212
|
+
Common.printOut(' If you arent sure, just run : zm2 startup')
|
|
213
|
+
Common.printOut('-----------------------------------------------------------')
|
|
214
|
+
}
|
|
215
|
+
if (platform == null)
|
|
216
|
+
throw new Error('Init system not found');
|
|
217
|
+
|
|
218
|
+
if (!cb) {
|
|
219
|
+
cb = function(err, data) {
|
|
220
|
+
if (err)
|
|
221
|
+
return that.exitCli(cst.ERROR_EXIT);
|
|
222
|
+
return that.exitCli(cst.SUCCESS_EXIT);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
if (process.getuid() != 0) {
|
|
227
|
+
return isNotRoot('setup', platform, opts, cb);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
var destination;
|
|
231
|
+
var commands;
|
|
232
|
+
var template;
|
|
233
|
+
|
|
234
|
+
function getTemplate(type) {
|
|
235
|
+
return fs.readFileSync(path.join(__dirname, '..', 'templates/init-scripts', type + '.tpl'), {encoding: 'utf8'});
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
switch(platform) {
|
|
239
|
+
case 'ubuntu':
|
|
240
|
+
case 'centos':
|
|
241
|
+
case 'arch':
|
|
242
|
+
case 'oracle':
|
|
243
|
+
case 'systemd':
|
|
244
|
+
if (opts.waitIp)
|
|
245
|
+
template = getTemplate('systemd-online');
|
|
246
|
+
else
|
|
247
|
+
template = getTemplate('systemd');
|
|
248
|
+
destination = '/etc/systemd/system/' + service_name + '.service';
|
|
249
|
+
commands = [
|
|
250
|
+
'systemctl enable ' + service_name
|
|
251
|
+
];
|
|
252
|
+
break;
|
|
253
|
+
case 'ubuntu14':
|
|
254
|
+
case 'ubuntu12':
|
|
255
|
+
case 'upstart':
|
|
256
|
+
template = getTemplate('upstart');
|
|
257
|
+
destination = '/etc/init.d/' + service_name;
|
|
258
|
+
commands = [
|
|
259
|
+
'chmod +x ' + destination,
|
|
260
|
+
'mkdir -p /var/lock/subsys',
|
|
261
|
+
'touch /var/lock/subsys/' + service_name,
|
|
262
|
+
'update-rc.d ' + service_name + ' defaults'
|
|
263
|
+
];
|
|
264
|
+
break;
|
|
265
|
+
case 'systemv':
|
|
266
|
+
case 'amazon':
|
|
267
|
+
case 'centos6':
|
|
268
|
+
template = getTemplate('upstart');
|
|
269
|
+
destination = '/etc/init.d/' + service_name;
|
|
270
|
+
commands = [
|
|
271
|
+
'chmod +x ' + destination,
|
|
272
|
+
'mkdir -p /var/lock/subsys',
|
|
273
|
+
'touch /var/lock/subsys/' + service_name,
|
|
274
|
+
'chkconfig --add ' + service_name,
|
|
275
|
+
'chkconfig ' + service_name + ' on',
|
|
276
|
+
'initctl list'
|
|
277
|
+
];
|
|
278
|
+
break;
|
|
279
|
+
case 'macos':
|
|
280
|
+
case 'darwin':
|
|
281
|
+
case 'launchd':
|
|
282
|
+
template = getTemplate('launchd');
|
|
283
|
+
destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist');
|
|
284
|
+
commands = [
|
|
285
|
+
'mkdir -p ' + path.join(process.env.HOME, 'Library/LaunchAgents'),
|
|
286
|
+
'launchctl load -w ' + destination
|
|
287
|
+
]
|
|
288
|
+
break;
|
|
289
|
+
case 'freebsd':
|
|
290
|
+
case 'rcd':
|
|
291
|
+
template = getTemplate('rcd');
|
|
292
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
293
|
+
destination = '/usr/local/etc/rc.d/' + service_name;
|
|
294
|
+
commands = [
|
|
295
|
+
'chmod 755 ' + destination,
|
|
296
|
+
'sysrc ' + service_name + '_enable=YES'
|
|
297
|
+
];
|
|
298
|
+
break;
|
|
299
|
+
case 'openbsd':
|
|
300
|
+
case 'rcd-openbsd':
|
|
301
|
+
template = getTemplate('rcd-openbsd');
|
|
302
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
303
|
+
destination = path.join('/etc/rc.d/', service_name);
|
|
304
|
+
commands = [
|
|
305
|
+
'chmod 755 ' + destination,
|
|
306
|
+
'rcctl enable ' + service_name,
|
|
307
|
+
'rcctl start ' + service_name
|
|
308
|
+
];
|
|
309
|
+
break;
|
|
310
|
+
case 'openrc':
|
|
311
|
+
template = getTemplate('openrc');
|
|
312
|
+
service_name = openrc_service_name;
|
|
313
|
+
destination = '/etc/init.d/' + service_name;
|
|
314
|
+
commands = [
|
|
315
|
+
'chmod +x ' + destination,
|
|
316
|
+
'rc-update add ' + service_name + ' default'
|
|
317
|
+
];
|
|
318
|
+
break;
|
|
319
|
+
case 'smf':
|
|
320
|
+
case 'sunos':
|
|
321
|
+
case 'solaris':
|
|
322
|
+
template = getTemplate('smf');
|
|
323
|
+
service_name = (opts.serviceName || 'zm2_' + user);
|
|
324
|
+
destination = path.join(tmpPath(), service_name + '.xml');
|
|
325
|
+
commands = [
|
|
326
|
+
'svccfg import ' + destination,
|
|
327
|
+
'svcadm enable ' + service_name
|
|
328
|
+
];
|
|
329
|
+
break;
|
|
330
|
+
default:
|
|
331
|
+
throw new Error('Unknown platform / init system name');
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* 4# Replace template variable value
|
|
336
|
+
*/
|
|
337
|
+
var envPath
|
|
338
|
+
|
|
339
|
+
if (cst.HAS_NODE_EMBEDDED == true)
|
|
340
|
+
envPath = util.format('%s:%s', process.env.PATH || '', path.dirname(process.execPath))
|
|
341
|
+
else if (new RegExp(path.dirname(process.execPath)).test(process.env.PATH))
|
|
342
|
+
envPath = process.env.PATH
|
|
343
|
+
else
|
|
344
|
+
envPath = util.format('%s:%s', process.env.PATH || '', path.dirname(process.execPath))
|
|
345
|
+
|
|
346
|
+
let pm2_bin_path = require.main.filename
|
|
347
|
+
|
|
348
|
+
if (pm2_bin_path.includes('/lib/binaries/CLI.js') === true) {
|
|
349
|
+
pm2_bin_path = pm2_bin_path.replace('/lib/binaries/CLI.js', '/bin/zm2')
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
template = template.replace(/%PM2_PATH%/g, pm2_bin_path)
|
|
353
|
+
.replace(/%NODE_PATH%/g, envPath)
|
|
354
|
+
.replace(/%USER%/g, user)
|
|
355
|
+
.replace(/%HOME_PATH%/g, opts.hp ? path.resolve(opts.hp, '.pm2') : cst.PM2_ROOT_PATH)
|
|
356
|
+
.replace(/%SERVICE_NAME%/g, service_name);
|
|
357
|
+
|
|
358
|
+
Common.printOut(chalk.bold('Platform'), platform);
|
|
359
|
+
Common.printOut(chalk.bold('Template'));
|
|
360
|
+
Common.printOut(template);
|
|
361
|
+
Common.printOut(chalk.bold('Target path'));
|
|
362
|
+
Common.printOut(destination);
|
|
363
|
+
Common.printOut(chalk.bold('Command list'));
|
|
364
|
+
Common.printOut(commands);
|
|
365
|
+
|
|
366
|
+
Common.printOut(cst.PREFIX_MSG + 'Writing init configuration in ' + destination);
|
|
367
|
+
try {
|
|
368
|
+
fs.writeFileSync(destination, template);
|
|
369
|
+
} catch (e) {
|
|
370
|
+
console.error(cst.PREFIX_MSG_ERR + 'Failure when trying to write startup script');
|
|
371
|
+
console.error(e.message || e);
|
|
372
|
+
return cb(e);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
Common.printOut(cst.PREFIX_MSG + 'Making script booting at startup...');
|
|
376
|
+
|
|
377
|
+
forEachLimit(commands, 1, function(command, next) {
|
|
378
|
+
Common.printOut(cst.PREFIX_MSG + '[-] Executing: %s...', chalk.bold(command));
|
|
379
|
+
|
|
380
|
+
sexec(command, function(code, stdout, stderr) {
|
|
381
|
+
if (code === 0) {
|
|
382
|
+
Common.printOut(cst.PREFIX_MSG + chalk.bold('[v] Command successfully executed.'));
|
|
383
|
+
return next();
|
|
384
|
+
} else {
|
|
385
|
+
Common.printOut(chalk.red('[ERROR] Exit code : ' + code))
|
|
386
|
+
return next(new Error(command + ' failed, see error above.'));
|
|
387
|
+
}
|
|
388
|
+
})
|
|
389
|
+
|
|
390
|
+
}, function(err) {
|
|
391
|
+
if (err) {
|
|
392
|
+
console.error(cst.PREFIX_MSG_ERR + (err.message || err));
|
|
393
|
+
return cb(err);
|
|
394
|
+
}
|
|
395
|
+
Common.printOut(chalk.bold.blue('+---------------------------------------+'));
|
|
396
|
+
Common.printOut(chalk.bold.blue((cst.PREFIX_MSG + 'Freeze a process list on reboot via:' )));
|
|
397
|
+
Common.printOut(chalk.bold('$ zm2 save'));
|
|
398
|
+
Common.printOut('');
|
|
399
|
+
Common.printOut(chalk.bold.blue(cst.PREFIX_MSG + 'Remove init script via:'));
|
|
400
|
+
Common.printOut(chalk.bold('$ zm2 unstartup ' + platform));
|
|
401
|
+
|
|
402
|
+
return cb(null, {
|
|
403
|
+
destination : destination,
|
|
404
|
+
template : template
|
|
405
|
+
});
|
|
406
|
+
});
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* DISABLED FEATURE
|
|
411
|
+
* KEEPING METHOD FOR BACKWARD COMPAT
|
|
412
|
+
*/
|
|
413
|
+
CLI.prototype.autodump = function(cb) {
|
|
414
|
+
return cb()
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Dump current processes managed by pm2 into DUMP_FILE_PATH file
|
|
419
|
+
* @method dump
|
|
420
|
+
* @param {} cb
|
|
421
|
+
* @return
|
|
422
|
+
*/
|
|
423
|
+
CLI.prototype.dump = function(force, cb) {
|
|
424
|
+
var env_arr = [];
|
|
425
|
+
var that = this;
|
|
426
|
+
|
|
427
|
+
if (typeof(force) === 'function') {
|
|
428
|
+
cb = force
|
|
429
|
+
force = false
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if (!cb)
|
|
433
|
+
Common.printOut(cst.PREFIX_MSG + 'Saving current process list...');
|
|
434
|
+
|
|
435
|
+
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
|
|
436
|
+
if (err) {
|
|
437
|
+
Common.printError('Error retrieving process list: ' + err);
|
|
438
|
+
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Description
|
|
443
|
+
* @method fin
|
|
444
|
+
* @param {} err
|
|
445
|
+
* @return
|
|
446
|
+
*/
|
|
447
|
+
function fin(err) {
|
|
448
|
+
|
|
449
|
+
// try to fix issues with empty dump file
|
|
450
|
+
// like #3485
|
|
451
|
+
if (!force && env_arr.length === 0 && !process.env.FORCE) {
|
|
452
|
+
|
|
453
|
+
// fix : if no dump file, no process, only module and after pm2 update
|
|
454
|
+
if (!fs.existsSync(cst.DUMP_FILE_PATH)) {
|
|
455
|
+
that.clearDump(function(){});
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// if no process in list don't modify dump file
|
|
459
|
+
// process list should not be empty
|
|
460
|
+
if (cb) {
|
|
461
|
+
return cb(new Error('Process list empty, cannot save empty list'));
|
|
462
|
+
} else {
|
|
463
|
+
Common.printOut(cst.PREFIX_MSG_WARNING + 'ZM2 is not managing any process, skipping save...');
|
|
464
|
+
Common.printOut(cst.PREFIX_MSG_WARNING + 'To force saving use: zm2 save --force');
|
|
465
|
+
that.exitCli(cst.SUCCESS_EXIT);
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Back up dump file
|
|
471
|
+
try {
|
|
472
|
+
if (fs.existsSync(cst.DUMP_FILE_PATH)) {
|
|
473
|
+
fs.writeFileSync(cst.DUMP_BACKUP_FILE_PATH, fs.readFileSync(cst.DUMP_FILE_PATH));
|
|
474
|
+
}
|
|
475
|
+
} catch (e) {
|
|
476
|
+
console.error(e.stack || e);
|
|
477
|
+
Common.printOut(cst.PREFIX_MSG_ERR + 'Failed to back up dump file in %s', cst.DUMP_BACKUP_FILE_PATH);
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
// Overwrite dump file, delete if broken and exit
|
|
481
|
+
try {
|
|
482
|
+
fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify(env_arr, '', 2));
|
|
483
|
+
} catch (e) {
|
|
484
|
+
console.error(e.stack || e);
|
|
485
|
+
try {
|
|
486
|
+
// try to backup file
|
|
487
|
+
if (fs.existsSync(cst.DUMP_BACKUP_FILE_PATH)) {
|
|
488
|
+
fs.writeFileSync(cst.DUMP_FILE_PATH, fs.readFileSync(cst.DUMP_BACKUP_FILE_PATH));
|
|
489
|
+
}
|
|
490
|
+
} catch (e) {
|
|
491
|
+
// don't keep broken file
|
|
492
|
+
fs.unlinkSync(cst.DUMP_FILE_PATH);
|
|
493
|
+
console.error(e.stack || e);
|
|
494
|
+
}
|
|
495
|
+
Common.printOut(cst.PREFIX_MSG_ERR + 'Failed to save dump file in %s', cst.DUMP_FILE_PATH);
|
|
496
|
+
return that.exitCli(cst.ERROR_EXIT);
|
|
497
|
+
}
|
|
498
|
+
if (cb) return cb(null, {success:true});
|
|
499
|
+
|
|
500
|
+
Common.printOut(cst.PREFIX_MSG + 'Successfully saved in %s', cst.DUMP_FILE_PATH);
|
|
501
|
+
return that.exitCli(cst.SUCCESS_EXIT);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
(function ex(apps) {
|
|
505
|
+
if (!apps[0]) return fin(null);
|
|
506
|
+
delete apps[0].pm2_env.instances;
|
|
507
|
+
delete apps[0].pm2_env.pm_id;
|
|
508
|
+
delete apps[0].pm2_env.prev_restart_delay;
|
|
509
|
+
if (!apps[0].pm2_env.pmx_module)
|
|
510
|
+
env_arr.push(apps[0].pm2_env);
|
|
511
|
+
apps.shift();
|
|
512
|
+
return ex(apps);
|
|
513
|
+
})(list);
|
|
514
|
+
});
|
|
515
|
+
};
|
|
516
|
+
|
|
517
|
+
/**
|
|
518
|
+
* Remove DUMP_FILE_PATH file and DUMP_BACKUP_FILE_PATH file
|
|
519
|
+
* @method dump
|
|
520
|
+
* @param {} cb
|
|
521
|
+
* @return
|
|
522
|
+
*/
|
|
523
|
+
CLI.prototype.clearDump = function(cb) {
|
|
524
|
+
fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify([]));
|
|
525
|
+
|
|
526
|
+
if(cb && typeof cb === 'function') return cb();
|
|
527
|
+
|
|
528
|
+
Common.printOut(cst.PREFIX_MSG + 'Successfully created %s', cst.DUMP_FILE_PATH);
|
|
529
|
+
return this.exitCli(cst.SUCCESS_EXIT);
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Resurrect processes
|
|
534
|
+
* @method resurrect
|
|
535
|
+
* @param {} cb
|
|
536
|
+
* @return
|
|
537
|
+
*/
|
|
538
|
+
CLI.prototype.resurrect = function(cb) {
|
|
539
|
+
var apps = {};
|
|
540
|
+
var that = this;
|
|
541
|
+
|
|
542
|
+
var processes;
|
|
543
|
+
|
|
544
|
+
function readDumpFile(dumpFilePath) {
|
|
545
|
+
Common.printOut(cst.PREFIX_MSG + 'Restoring processes located in %s', dumpFilePath);
|
|
546
|
+
try {
|
|
547
|
+
var apps = fs.readFileSync(dumpFilePath);
|
|
548
|
+
} catch (e) {
|
|
549
|
+
Common.printError(cst.PREFIX_MSG_ERR + 'Failed to read dump file in %s', dumpFilePath);
|
|
550
|
+
throw e;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
return apps;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
function parseDumpFile(dumpFilePath, apps) {
|
|
557
|
+
try {
|
|
558
|
+
var processes = Common.parseConfig(apps, 'none');
|
|
559
|
+
} catch (e) {
|
|
560
|
+
Common.printError(cst.PREFIX_MSG_ERR + 'Failed to parse dump file in %s', dumpFilePath);
|
|
561
|
+
try {
|
|
562
|
+
fs.unlinkSync(dumpFilePath);
|
|
563
|
+
} catch (e) {
|
|
564
|
+
console.error(e.stack || e);
|
|
565
|
+
}
|
|
566
|
+
throw e;
|
|
567
|
+
}
|
|
568
|
+
|
|
569
|
+
return processes;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
// Read dump file, fall back to backup, delete if broken
|
|
573
|
+
try {
|
|
574
|
+
apps = readDumpFile(cst.DUMP_FILE_PATH);
|
|
575
|
+
processes = parseDumpFile(cst.DUMP_FILE_PATH, apps);
|
|
576
|
+
} catch(e) {
|
|
577
|
+
try {
|
|
578
|
+
apps = readDumpFile(cst.DUMP_BACKUP_FILE_PATH);
|
|
579
|
+
processes = parseDumpFile(cst.DUMP_BACKUP_FILE_PATH, apps);
|
|
580
|
+
} catch(e) {
|
|
581
|
+
Common.printError(cst.PREFIX_MSG_ERR + 'No processes saved; DUMP file doesn\'t exist');
|
|
582
|
+
// if (cb) return cb(Common.retErr(e));
|
|
583
|
+
// else return that.exitCli(cst.ERROR_EXIT);
|
|
584
|
+
return that.speedList();
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
|
|
588
|
+
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
|
|
589
|
+
if (err) {
|
|
590
|
+
Common.printError(err);
|
|
591
|
+
return that.exitCli(1);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
var current = [];
|
|
595
|
+
var target = [];
|
|
596
|
+
|
|
597
|
+
list.forEach(function(app) {
|
|
598
|
+
if (!current[app.name])
|
|
599
|
+
current[app.name] = 0;
|
|
600
|
+
current[app.name]++;
|
|
601
|
+
});
|
|
602
|
+
|
|
603
|
+
processes.forEach(function(app) {
|
|
604
|
+
if (!target[app.name])
|
|
605
|
+
target[app.name] = 0;
|
|
606
|
+
target[app.name]++;
|
|
607
|
+
});
|
|
608
|
+
|
|
609
|
+
var tostart = Object.keys(target).filter(function(i) {
|
|
610
|
+
return Object.keys(current).indexOf(i) < 0;
|
|
611
|
+
})
|
|
612
|
+
|
|
613
|
+
eachLimit(processes, cst.CONCURRENT_ACTIONS, function(app, next) {
|
|
614
|
+
if (tostart.indexOf(app.name) == -1)
|
|
615
|
+
return next();
|
|
616
|
+
that.Client.executeRemote('prepare', app, function(err, dt) {
|
|
617
|
+
if (err)
|
|
618
|
+
Common.printError(err);
|
|
619
|
+
else
|
|
620
|
+
Common.printOut(cst.PREFIX_MSG + 'Process %s restored', app.pm_exec_path);
|
|
621
|
+
next();
|
|
622
|
+
});
|
|
623
|
+
}, function(err) {
|
|
624
|
+
return cb ? cb(null, apps) : that.speedList();
|
|
625
|
+
});
|
|
626
|
+
});
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
}
|