@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,33 @@
|
|
|
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 url = require('url');
|
|
7
|
+
// Inject custom modules
|
|
8
|
+
var ProcessUtils = require('./ProcessUtils')
|
|
9
|
+
ProcessUtils.injectModules()
|
|
10
|
+
|
|
11
|
+
if (typeof(process.env.source_map_support) != "undefined" &&
|
|
12
|
+
process.env.source_map_support !== "false") {
|
|
13
|
+
require('source-map-support').install();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Rename the process
|
|
17
|
+
process.title = process.env.PROCESS_TITLE || 'bun ' + process.env.pm_exec_path;
|
|
18
|
+
|
|
19
|
+
if (process.connected &&
|
|
20
|
+
process.send &&
|
|
21
|
+
process.versions &&
|
|
22
|
+
process.versions.node)
|
|
23
|
+
process.send({
|
|
24
|
+
'node_version': process.versions.node
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
require(process.env.pm_exec_path);
|
|
28
|
+
|
|
29
|
+
// Change some values to make node think that the user's application
|
|
30
|
+
// was started directly such as `node app.js`
|
|
31
|
+
process.mainModule = process.mainModule || {};
|
|
32
|
+
process.mainModule.loaded = false;
|
|
33
|
+
require.main = process.mainModule;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use strict'
|
|
2
|
+
|
|
3
|
+
module.exports = {
|
|
4
|
+
injectModules: function() {
|
|
5
|
+
if (process.env.pmx !== 'false') {
|
|
6
|
+
const pmx = require('@pm2/io')
|
|
7
|
+
|
|
8
|
+
let conf = {}
|
|
9
|
+
const hasSpecificConfig = typeof process.env.io === 'string' || process.env.trace === 'true'
|
|
10
|
+
// pmx is already init, no need to do it twice
|
|
11
|
+
if (hasSpecificConfig === false) return
|
|
12
|
+
|
|
13
|
+
if (process.env.io) {
|
|
14
|
+
const io = JSON.parse(process.env.io)
|
|
15
|
+
conf = io.conf ? io.conf : conf
|
|
16
|
+
}
|
|
17
|
+
pmx.init(Object.assign({
|
|
18
|
+
tracing: process.env.trace === 'true' || false
|
|
19
|
+
}, conf))
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
isESModule(exec_path) {
|
|
23
|
+
var fs = require('fs')
|
|
24
|
+
var path = require('path')
|
|
25
|
+
var semver = require('semver')
|
|
26
|
+
var data
|
|
27
|
+
|
|
28
|
+
var findPackageJson = function(directory) {
|
|
29
|
+
var file = path.join(directory, 'package.json')
|
|
30
|
+
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
|
|
31
|
+
return file;
|
|
32
|
+
}
|
|
33
|
+
var parent = path.resolve(directory, '..')
|
|
34
|
+
if (parent === directory) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return findPackageJson(parent)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
if (semver.satisfies(process.version, '< 13.3.0'))
|
|
41
|
+
return false
|
|
42
|
+
|
|
43
|
+
if (path.extname(exec_path) === '.mjs')
|
|
44
|
+
return true
|
|
45
|
+
|
|
46
|
+
try {
|
|
47
|
+
data = JSON.parse(fs.readFileSync(findPackageJson(path.dirname(exec_path))))
|
|
48
|
+
if (data.type === 'module')
|
|
49
|
+
return true
|
|
50
|
+
else
|
|
51
|
+
return false
|
|
52
|
+
} catch(e) {
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
package/lib/TreeKill.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// From https://raw.githubusercontent.com/pkrumins/node-tree-kill/master/index.js
|
|
4
|
+
|
|
5
|
+
var childProcess = require('child_process');
|
|
6
|
+
var spawn = childProcess.spawn;
|
|
7
|
+
var exec = childProcess.exec;
|
|
8
|
+
|
|
9
|
+
module.exports = function (pid, signal, callback) {
|
|
10
|
+
var tree = {};
|
|
11
|
+
var pidsToProcess = {};
|
|
12
|
+
tree[pid] = [];
|
|
13
|
+
pidsToProcess[pid] = 1;
|
|
14
|
+
|
|
15
|
+
switch (process.platform) {
|
|
16
|
+
case 'win32':
|
|
17
|
+
exec('taskkill /pid ' + pid + ' /T /F', { windowsHide: true }, callback);
|
|
18
|
+
break;
|
|
19
|
+
case 'freebsd':
|
|
20
|
+
case 'darwin':
|
|
21
|
+
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
|
|
22
|
+
return spawn('pgrep', ['-P', parentPid]);
|
|
23
|
+
}, function () {
|
|
24
|
+
killAll(tree, signal, callback);
|
|
25
|
+
});
|
|
26
|
+
break;
|
|
27
|
+
// case 'sunos':
|
|
28
|
+
// buildProcessTreeSunOS(pid, tree, pidsToProcess, function () {
|
|
29
|
+
// killAll(tree, signal, callback);
|
|
30
|
+
// });
|
|
31
|
+
// break;
|
|
32
|
+
default: // Linux
|
|
33
|
+
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
|
|
34
|
+
return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
|
|
35
|
+
}, function () {
|
|
36
|
+
killAll(tree, signal, callback);
|
|
37
|
+
});
|
|
38
|
+
break;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
function killAll (tree, signal, callback) {
|
|
43
|
+
var killed = {};
|
|
44
|
+
try {
|
|
45
|
+
Object.keys(tree).forEach(function (pid) {
|
|
46
|
+
tree[pid].forEach(function (pidpid) {
|
|
47
|
+
if (!killed[pidpid]) {
|
|
48
|
+
killPid(pidpid, signal);
|
|
49
|
+
killed[pidpid] = 1;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
if (!killed[pid]) {
|
|
53
|
+
killPid(pid, signal);
|
|
54
|
+
killed[pid] = 1;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
} catch (err) {
|
|
58
|
+
if (callback) {
|
|
59
|
+
return callback(err);
|
|
60
|
+
} else {
|
|
61
|
+
console.error(err);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (callback) {
|
|
65
|
+
return callback();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function killPid(pid, signal) {
|
|
70
|
+
try {
|
|
71
|
+
process.kill(parseInt(pid, 10), signal);
|
|
72
|
+
}
|
|
73
|
+
catch (err) {
|
|
74
|
+
if (err.code !== 'ESRCH')
|
|
75
|
+
console.error(err);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesList, cb) {
|
|
80
|
+
var ps = spawnChildProcessesList(parentPid);
|
|
81
|
+
var allData = '';
|
|
82
|
+
|
|
83
|
+
ps.on('error', function(err) {
|
|
84
|
+
console.error(err);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
if (ps.stdout) {
|
|
88
|
+
ps.stdout.on('data', function (data) {
|
|
89
|
+
data = data.toString('ascii');
|
|
90
|
+
allData += data;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
var onClose = function (code) {
|
|
95
|
+
delete pidsToProcess[parentPid];
|
|
96
|
+
|
|
97
|
+
if (code !== 0) {
|
|
98
|
+
// no more parent processes
|
|
99
|
+
if (Object.keys(pidsToProcess).length == 0) {
|
|
100
|
+
cb();
|
|
101
|
+
}
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
var pids = allData.match(/\d+/g) || [];
|
|
105
|
+
if (pids.length === 0)
|
|
106
|
+
return cb();
|
|
107
|
+
|
|
108
|
+
pids.forEach(function (pid) {
|
|
109
|
+
pid = parseInt(pid, 10);
|
|
110
|
+
tree[parentPid].push(pid);
|
|
111
|
+
tree[pid] = [];
|
|
112
|
+
pidsToProcess[pid] = 1;
|
|
113
|
+
buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb);
|
|
114
|
+
});
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
ps.on('close', onClose);
|
|
118
|
+
}
|
package/lib/Utility.js
ADDED
|
@@ -0,0 +1,430 @@
|
|
|
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
|
+
/**
|
|
8
|
+
* Common Utilities ONLY USED IN ->DAEMON<-
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
var fclone = require('fclone');
|
|
12
|
+
var fs = require('fs');
|
|
13
|
+
var dgram = require('dgram');
|
|
14
|
+
var os = require('os');
|
|
15
|
+
var cst = require('../constants.js');
|
|
16
|
+
var waterfall = require('async/waterfall');
|
|
17
|
+
var util = require('util');
|
|
18
|
+
var url = require('url');
|
|
19
|
+
var dayjs = require('dayjs');
|
|
20
|
+
var findPackageJson = require('./tools/find-package-json')
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Syslog severity levels
|
|
24
|
+
*/
|
|
25
|
+
var SYSLOG_SEVERITY = {
|
|
26
|
+
err: 3, // LOG_ERR
|
|
27
|
+
out: 6, // LOG_INFO
|
|
28
|
+
std: 6 // LOG_INFO
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
var SYSLOG_FACILITY_USER = 1;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Resolve the syslog unix socket path based on platform
|
|
35
|
+
*/
|
|
36
|
+
function getSyslogSocketPath() {
|
|
37
|
+
if (os.platform() === 'darwin')
|
|
38
|
+
return '/var/run/syslog';
|
|
39
|
+
return '/dev/log';
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* SyslogStream - A writable stream that sends messages to syslog via unix socket.
|
|
44
|
+
* Implements the same interface as fs.WriteStream so it can be used as a drop-in
|
|
45
|
+
* replacement in PM2's logging pipeline.
|
|
46
|
+
*
|
|
47
|
+
* @param {string} appName - Application name for syslog tag
|
|
48
|
+
* @param {number} pid - Process ID
|
|
49
|
+
* @param {string} type - Stream type: 'out', 'err', or 'std'
|
|
50
|
+
* @param {string} filePath - Original file path (stored as _file for reload compatibility)
|
|
51
|
+
*/
|
|
52
|
+
function SyslogStream(appName, pid, type, filePath) {
|
|
53
|
+
this._appName = appName || 'pm2';
|
|
54
|
+
this._pid = pid || process.pid;
|
|
55
|
+
this._type = type || 'out';
|
|
56
|
+
this._file = filePath;
|
|
57
|
+
this._destroyed = false;
|
|
58
|
+
|
|
59
|
+
var severity = SYSLOG_SEVERITY[this._type] || 6;
|
|
60
|
+
this._priority = SYSLOG_FACILITY_USER * 8 + severity;
|
|
61
|
+
|
|
62
|
+
this._socketPath = getSyslogSocketPath();
|
|
63
|
+
this._socket = null;
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
this._socket = dgram.createSocket('unix_dgram');
|
|
67
|
+
this._socket.on('error', function(err) {
|
|
68
|
+
console.error('PM2 syslog socket error:', err.message);
|
|
69
|
+
});
|
|
70
|
+
} catch (e) {
|
|
71
|
+
console.error('PM2 syslog: failed to create unix_dgram socket:', e.message);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
SyslogStream.prototype.write = function(data, encoding, cb) {
|
|
76
|
+
if (this._destroyed || !this._socket) {
|
|
77
|
+
if (cb) cb();
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
var lines = data.toString().split('\n');
|
|
82
|
+
for (var i = 0; i < lines.length; i++) {
|
|
83
|
+
if (lines[i].length === 0) continue;
|
|
84
|
+
|
|
85
|
+
var msg = '<' + this._priority + '>' + this._appName + '[' + this._pid + ']: ' + lines[i];
|
|
86
|
+
var buf = Buffer.from(msg);
|
|
87
|
+
|
|
88
|
+
try {
|
|
89
|
+
this._socket.send(buf, 0, buf.length, this._socketPath);
|
|
90
|
+
} catch (e) {
|
|
91
|
+
// Socket may be unavailable; swallow error to avoid crashing the app
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if (cb) cb();
|
|
96
|
+
return true;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
SyslogStream.prototype.destroy = function() {
|
|
100
|
+
if (this._destroyed) return;
|
|
101
|
+
this._destroyed = true;
|
|
102
|
+
if (this._socket) {
|
|
103
|
+
try { this._socket.close(); } catch (e) {}
|
|
104
|
+
this._socket = null;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
SyslogStream.prototype.end = function() { this.destroy(); };
|
|
109
|
+
SyslogStream.prototype.close = function() { this.destroy(); };
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* DualStream - Writes to both a file stream and a syslog stream.
|
|
113
|
+
*
|
|
114
|
+
* @param {object} fileStream - fs.WriteStream instance
|
|
115
|
+
* @param {object} syslogStream - SyslogStream instance
|
|
116
|
+
* @param {string} filePath - Original file path (stored as _file for reload compatibility)
|
|
117
|
+
*/
|
|
118
|
+
function DualStream(fileStream, syslogStream, filePath) {
|
|
119
|
+
this._fileStream = fileStream;
|
|
120
|
+
this._syslogStream = syslogStream;
|
|
121
|
+
this._file = filePath;
|
|
122
|
+
this._destroyed = false;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
DualStream.prototype.write = function(data, encoding, cb) {
|
|
126
|
+
if (this._destroyed) {
|
|
127
|
+
if (cb) cb();
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
this._syslogStream.write(data, encoding);
|
|
131
|
+
return this._fileStream.write(data, encoding, cb);
|
|
132
|
+
};
|
|
133
|
+
|
|
134
|
+
DualStream.prototype.destroy = function() {
|
|
135
|
+
if (this._destroyed) return;
|
|
136
|
+
this._destroyed = true;
|
|
137
|
+
if (this._fileStream && this._fileStream.destroy) this._fileStream.destroy();
|
|
138
|
+
if (this._syslogStream) this._syslogStream.destroy();
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
DualStream.prototype.end = function() { this.destroy(); };
|
|
142
|
+
DualStream.prototype.close = function() { this.destroy(); };
|
|
143
|
+
|
|
144
|
+
var Utility = module.exports = {
|
|
145
|
+
findPackageVersion : function(fullpath) {
|
|
146
|
+
var version
|
|
147
|
+
|
|
148
|
+
try {
|
|
149
|
+
version = findPackageJson(fullpath).next().value.version
|
|
150
|
+
} catch(e) {
|
|
151
|
+
version = 'N/A'
|
|
152
|
+
}
|
|
153
|
+
return version
|
|
154
|
+
},
|
|
155
|
+
getDate : function() {
|
|
156
|
+
return Date.now();
|
|
157
|
+
},
|
|
158
|
+
extendExtraConfig : function(proc, opts) {
|
|
159
|
+
if (opts.env && opts.env.current_conf) {
|
|
160
|
+
if (opts.env.current_conf.env &&
|
|
161
|
+
typeof(opts.env.current_conf.env) === 'object' &&
|
|
162
|
+
Object.keys(opts.env.current_conf.env).length === 0)
|
|
163
|
+
delete opts.env.current_conf.env
|
|
164
|
+
|
|
165
|
+
Utility.extendMix(proc.pm2_env, opts.env.current_conf);
|
|
166
|
+
delete opts.env.current_conf;
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
formatCLU : function(process) {
|
|
170
|
+
if (!process.pm2_env) {
|
|
171
|
+
return process;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
var obj = Utility.clone(process.pm2_env);
|
|
175
|
+
delete obj.env;
|
|
176
|
+
|
|
177
|
+
return obj;
|
|
178
|
+
},
|
|
179
|
+
extend : function(destination, source){
|
|
180
|
+
if (!source || typeof source != 'object') return destination;
|
|
181
|
+
|
|
182
|
+
Object.keys(source).forEach(function(new_key) {
|
|
183
|
+
if (source[new_key] != '[object Object]')
|
|
184
|
+
destination[new_key] = source[new_key];
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
return destination;
|
|
188
|
+
},
|
|
189
|
+
// Same as extend but drop value with 'null'
|
|
190
|
+
extendMix : function(destination, source){
|
|
191
|
+
if (!source || typeof source != 'object') return destination;
|
|
192
|
+
|
|
193
|
+
Object.keys(source).forEach(function(new_key) {
|
|
194
|
+
if (source[new_key] == 'null')
|
|
195
|
+
delete destination[new_key];
|
|
196
|
+
else
|
|
197
|
+
destination[new_key] = source[new_key]
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
return destination;
|
|
201
|
+
},
|
|
202
|
+
|
|
203
|
+
whichFileExists : function(file_arr) {
|
|
204
|
+
var f = null;
|
|
205
|
+
|
|
206
|
+
file_arr.some(function(file) {
|
|
207
|
+
try {
|
|
208
|
+
fs.statSync(file);
|
|
209
|
+
} catch(e) {
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
f = file;
|
|
213
|
+
return true;
|
|
214
|
+
});
|
|
215
|
+
return f;
|
|
216
|
+
},
|
|
217
|
+
clone : function(obj) {
|
|
218
|
+
if (obj === null || obj === undefined) return {};
|
|
219
|
+
return fclone(obj);
|
|
220
|
+
},
|
|
221
|
+
overrideConsole : function(bus) {
|
|
222
|
+
if (cst.PM2_LOG_DATE_FORMAT && typeof cst.PM2_LOG_DATE_FORMAT == 'string') {
|
|
223
|
+
// Generate timestamp prefix
|
|
224
|
+
function timestamp(){
|
|
225
|
+
return `${dayjs(Date.now()).format(cst.PM2_LOG_DATE_FORMAT)}:`;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
var hacks = ['info', 'log', 'error', 'warn'], consoled = {};
|
|
229
|
+
|
|
230
|
+
// store console functions.
|
|
231
|
+
hacks.forEach(function(method){
|
|
232
|
+
consoled[method] = console[method];
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
hacks.forEach(function(k){
|
|
236
|
+
console[k] = function(){
|
|
237
|
+
if (bus) {
|
|
238
|
+
bus.emit('log:PM2', {
|
|
239
|
+
process : {
|
|
240
|
+
pm_id : 'PM2',
|
|
241
|
+
name : 'PM2',
|
|
242
|
+
rev : null
|
|
243
|
+
},
|
|
244
|
+
at : Utility.getDate(),
|
|
245
|
+
data : util.format.apply(this, arguments) + '\n'
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
// do not destroy variable insertion
|
|
249
|
+
arguments[0] && (arguments[0] = timestamp() + ' PM2 ' + k + ': ' + arguments[0]);
|
|
250
|
+
consoled[k].apply(console, arguments);
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
startLogging : function(stds, pm2_env, callback) {
|
|
256
|
+
/**
|
|
257
|
+
* Start log outgoing messages
|
|
258
|
+
* @method startLogging
|
|
259
|
+
* @param {object} stds - Stream targets {out, err, std}
|
|
260
|
+
* @param {object} [pm2_env] - Process environment (optional, for backward compat)
|
|
261
|
+
* @param {function} callback
|
|
262
|
+
* @return
|
|
263
|
+
*/
|
|
264
|
+
|
|
265
|
+
// Backward compatibility: startLogging(stds, callback)
|
|
266
|
+
if (typeof pm2_env === 'function') {
|
|
267
|
+
callback = pm2_env;
|
|
268
|
+
pm2_env = null;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
var transport = (pm2_env && pm2_env.log_transport) || 'file';
|
|
272
|
+
|
|
273
|
+
// waterfall.
|
|
274
|
+
var flows = [];
|
|
275
|
+
// types of stdio, should be sorted as `std(entire log)`, `out`, `err`.
|
|
276
|
+
var types = Object.keys(stds).sort(function(x, y){
|
|
277
|
+
return -x.charCodeAt(0) + y.charCodeAt(0);
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Create write streams.
|
|
281
|
+
(function createWS(io){
|
|
282
|
+
if(io.length != 1){
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
285
|
+
io = io[0];
|
|
286
|
+
|
|
287
|
+
// If `std` is a Stream type, try next `std`.
|
|
288
|
+
// compatible with `pm2 reloadLogs`
|
|
289
|
+
if(typeof stds[io] == 'object' && !isNaN(stds[io].fd)){
|
|
290
|
+
return createWS(types.splice(0, 1));
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
flows.push(function(next){
|
|
294
|
+
var file = stds[io];
|
|
295
|
+
|
|
296
|
+
// if file contains ERR or /dev/null, dont try to create stream since he dont want logs
|
|
297
|
+
if (!file || file.indexOf('NULL') > -1 || file.indexOf('/dev/null') > -1)
|
|
298
|
+
return next();
|
|
299
|
+
|
|
300
|
+
if (transport === 'syslog') {
|
|
301
|
+
var appName = (pm2_env && pm2_env.name) || 'pm2';
|
|
302
|
+
var pid = (pm2_env && pm2_env.pm_id) || process.pid;
|
|
303
|
+
stds[io] = new SyslogStream(appName, pid, io, file);
|
|
304
|
+
stds[io]._file = file;
|
|
305
|
+
return next();
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (transport === 'both') {
|
|
309
|
+
var appName = (pm2_env && pm2_env.name) || 'pm2';
|
|
310
|
+
var pid = (pm2_env && pm2_env.pm_id) || process.pid;
|
|
311
|
+
var sysStream = new SyslogStream(appName, pid, io, file);
|
|
312
|
+
|
|
313
|
+
var fileStream = fs.createWriteStream(file, {flags: 'a'})
|
|
314
|
+
.once('error', next)
|
|
315
|
+
.on('open', function(){
|
|
316
|
+
fileStream.removeListener('error', next);
|
|
317
|
+
fileStream.on('error', function(err) {
|
|
318
|
+
console.error(err);
|
|
319
|
+
});
|
|
320
|
+
|
|
321
|
+
stds[io] = new DualStream(fileStream, sysStream, file);
|
|
322
|
+
stds[io]._file = file;
|
|
323
|
+
next();
|
|
324
|
+
});
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// Default: file transport
|
|
329
|
+
stds[io] = fs.createWriteStream(file, {flags: 'a'})
|
|
330
|
+
.once('error', next)
|
|
331
|
+
.on('open', function(){
|
|
332
|
+
stds[io].removeListener('error', next);
|
|
333
|
+
|
|
334
|
+
stds[io].on('error', function(err) {
|
|
335
|
+
console.error(err);
|
|
336
|
+
});
|
|
337
|
+
|
|
338
|
+
next();
|
|
339
|
+
});
|
|
340
|
+
stds[io]._file = file;
|
|
341
|
+
});
|
|
342
|
+
return createWS(types.splice(0, 1));
|
|
343
|
+
})(types.splice(0, 1));
|
|
344
|
+
|
|
345
|
+
waterfall(flows, callback);
|
|
346
|
+
},
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Function parse the module name and returns it as canonic:
|
|
350
|
+
* - Makes the name based on installation filename.
|
|
351
|
+
* - Removes the Github author, module version and git branch from original name.
|
|
352
|
+
*
|
|
353
|
+
* @param {string} module_name
|
|
354
|
+
* @returns {string} Canonic module name (without trimed parts).
|
|
355
|
+
* @example Always returns 'pm2-slack' for inputs 'ma-zal/pm2-slack', 'ma-zal/pm2-slack#own-branch',
|
|
356
|
+
* 'pm2-slack-1.0.0.tgz' or 'pm2-slack@1.0.0'.
|
|
357
|
+
*/
|
|
358
|
+
getCanonicModuleName: function(module_name) {
|
|
359
|
+
if (typeof module_name !== 'string') return null;
|
|
360
|
+
var canonic_module_name = module_name;
|
|
361
|
+
|
|
362
|
+
// Returns the module name from a .tgz package name (or the original name if it is not a valid pkg).
|
|
363
|
+
// Input: The package name (e.g. "foo.tgz", "foo-1.0.0.tgz", "folder/foo.tgz")
|
|
364
|
+
// Output: The module name
|
|
365
|
+
if (canonic_module_name.match(/\.tgz($|\?)/)) {
|
|
366
|
+
if (canonic_module_name.match(/^(.+\/)?([^\/]+)\.tgz($|\?)/)) {
|
|
367
|
+
canonic_module_name = canonic_module_name.match(/^(.+\/)?([^\/]+)\.tgz($|\?)/)[2];
|
|
368
|
+
if (canonic_module_name.match(/^(.+)-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+\.[0-9]+)?$/)) {
|
|
369
|
+
canonic_module_name = canonic_module_name.match(/^(.+)-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+\.[0-9]+)?$/)[1];
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
//pm2 install git+https://github.com/user/module
|
|
375
|
+
if(canonic_module_name.indexOf('git+') !== -1) {
|
|
376
|
+
canonic_module_name = canonic_module_name.split('/').pop();
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
//pm2 install https://github.com/user/module
|
|
380
|
+
if(canonic_module_name.indexOf('http') !== -1) {
|
|
381
|
+
var uri = url.parse(canonic_module_name);
|
|
382
|
+
canonic_module_name = uri.pathname.split('/').pop();
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
//pm2 install file:///home/user/module
|
|
386
|
+
else if(canonic_module_name.indexOf('file://') === 0) {
|
|
387
|
+
canonic_module_name = canonic_module_name.replace(/\/$/, '').split('/').pop();
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
//pm2 install username/module
|
|
391
|
+
else if(canonic_module_name.indexOf('/') !== -1) {
|
|
392
|
+
if (canonic_module_name.charAt(0) !== "@"){
|
|
393
|
+
canonic_module_name = canonic_module_name.split('/')[1];
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
//pm2 install @somescope/module@2.1.0-beta
|
|
398
|
+
if(canonic_module_name.lastIndexOf('@') > 0) {
|
|
399
|
+
canonic_module_name = canonic_module_name.substr(0,canonic_module_name.lastIndexOf("@"));
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
//pm2 install module#some-branch
|
|
403
|
+
if(canonic_module_name.indexOf('#') !== -1) {
|
|
404
|
+
canonic_module_name = canonic_module_name.split('#')[0];
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
if (canonic_module_name.indexOf('.git') !== -1) {
|
|
408
|
+
canonic_module_name = canonic_module_name.replace('.git', '');
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
return canonic_module_name;
|
|
412
|
+
},
|
|
413
|
+
|
|
414
|
+
checkPathIsNull: function(path) {
|
|
415
|
+
return path === 'NULL' || path === '/dev/null' || path === '\\\\.\\NUL';
|
|
416
|
+
},
|
|
417
|
+
|
|
418
|
+
generateUUID: function () {
|
|
419
|
+
var s = [];
|
|
420
|
+
var hexDigits = "0123456789abcdef";
|
|
421
|
+
for (var i = 0; i < 36; i++) {
|
|
422
|
+
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
|
|
423
|
+
}
|
|
424
|
+
s[14] = "4";
|
|
425
|
+
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
|
|
426
|
+
s[8] = s[13] = s[18] = s[23] = "-";
|
|
427
|
+
return s.join("");
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
|
|
2
|
+
var vCheck = require('@pm2/pm2-version-check')
|
|
3
|
+
var semver = require('semver')
|
|
4
|
+
var fs = require('fs')
|
|
5
|
+
var os = require('os')
|
|
6
|
+
|
|
7
|
+
function hasDockerEnv() {
|
|
8
|
+
try {
|
|
9
|
+
fs.statSync('/.dockerenv');
|
|
10
|
+
return true;
|
|
11
|
+
} catch (_) {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function hasDockerCGroup() {
|
|
17
|
+
try {
|
|
18
|
+
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
|
|
19
|
+
} catch (_) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
module.exports = function (opts) {
|
|
25
|
+
var params = {
|
|
26
|
+
state: opts.state,
|
|
27
|
+
version: opts.version
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
params.os = os.type()
|
|
32
|
+
params.uptime = Math.floor(process.uptime())
|
|
33
|
+
params.nodev = process.versions.node
|
|
34
|
+
params.docker = hasDockerEnv() || hasDockerCGroup()
|
|
35
|
+
} catch(e) {
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
vCheck.runCheck(params, (err, pkg) => {
|
|
39
|
+
if (err) return false
|
|
40
|
+
if (!pkg.current_version) return false
|
|
41
|
+
if (opts.version && semver.lt(opts.version, pkg.current_version)) {
|
|
42
|
+
console.log('[PM2] This PM2 is not UP TO DATE')
|
|
43
|
+
console.log('[PM2] Upgrade to version %s', pkg.current_version)
|
|
44
|
+
}
|
|
45
|
+
})
|
|
46
|
+
}
|