feat: 초기 프로젝트 설정 및 룰.md 파일 추가

This commit is contained in:
2025-07-28 09:53:31 +09:00
commit 09a4d38512
8165 changed files with 1021855 additions and 0 deletions

1929
api.hyungi.net/node_modules/pm2/lib/API.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,212 @@
var Common = require('../Common.js');
var cst = require('../../constants.js');
var UX = require('./UX');
var chalk = require('chalk');
var Configuration = require('../Configuration.js');
module.exports = function(CLI) {
CLI.prototype.get = function(key, cb) {
var that = this;
if (!key || key == 'all') {
displayConf(function(err, data) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
return false;
}
Configuration.get(key, function(err, data) {
if (err) {
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
// pm2 conf module-name
if (key.indexOf(':') === -1 && key.indexOf('.') === -1) {
displayConf(key, function() {
console.log('Modules configuration. Copy/Paste line to edit values.')
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
});
return false;
}
// pm2 conf module-name:key
var module_name, key_name;
if (key.indexOf(':') > -1) {
module_name = key.split(':')[0];
key_name = key.split(':')[1];
} else if (key.indexOf('.') > -1) {
module_name = key.split('.')[0];
key_name = key.split('.')[1];
}
Common.printOut('Value for module ' + chalk.blue(module_name), 'key ' + chalk.blue(key_name) + ': ' + chalk.bold.green(data));
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
};
CLI.prototype.set = function(key, value, cb) {
var that = this;
if (!key) {
interactiveConfigEdit(function(err) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
return false;
}
/**
* Set value
*/
Configuration.set(key, value, function(err) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
var values = [];
if (key.indexOf('.') > -1)
values = key.split('.');
if (key.indexOf(':') > -1)
values = key.split(':');
if (values && values.length > 1) {
// The first element is the app name (module_conf.json)
var app_name = values[0];
process.env.PM2_PROGRAMMATIC = 'true';
that.restart(app_name, {
updateEnv : true
}, function(err, data) {
process.env.PM2_PROGRAMMATIC = 'false';
if (!err)
Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
Common.log('Setting changed')
displayConf(app_name, function() {
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
});
return false;
}
displayConf(null, function() {
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
});
};
CLI.prototype.multiset = function(serial, cb) {
var that = this;
Configuration.multiset(serial, function(err, data) {
if (err)
return cb ? cb({success:false, err:err}) : that.exitCli(cst.ERROR_EXIT);
var values = [];
var key = serial.match(/(?:[^ "]+|"[^"]*")+/g)[0];
if (key.indexOf('.') > -1)
values = key.split('.');
if (key.indexOf(':') > -1)
values = key.split(':');
if (values && values.length > 1) {
// The first element is the app name (module_conf.json)
var app_name = values[0];
process.env.PM2_PROGRAMMATIC = 'true';
that.restart(app_name, {
updateEnv : true
}, function(err, data) {
process.env.PM2_PROGRAMMATIC = 'false';
if (!err)
Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
displayConf(app_name, function() {
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
});
});
return false;
}
displayConf(app_name, function() {
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
});
});
};
CLI.prototype.unset = function(key, cb) {
var that = this;
Configuration.unset(key, function(err) {
if (err) {
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
displayConf(function() { cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT) });
});
};
CLI.prototype.conf = function(key, value, cb) {
var that = this;
if (typeof(value) === 'function') {
cb = value;
value = null;
}
// If key + value = set
if (key && value) {
that.set(key, value, function(err) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
}
// If only key = get
else if (key) {
that.get(key, function(err, data) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
}
else {
interactiveConfigEdit(function(err) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
});
}
};
};
function interactiveConfigEdit(cb) {
UX.helpers.openEditor(cst.PM2_MODULE_CONF_FILE, function(err, data) {
Common.printOut(chalk.bold('Module configuration (%s) edited.'), cst.PM2_MODULE_CONF_FILE);
Common.printOut(chalk.bold('To take changes into account, please restart module related.'), cst.PM2_MODULE_CONF_FILE);
if (err)
return cb(Common.retErr(err));
return cb(null, {success:true});
});
}
/**
* Configuration
*/
function displayConf(target_app, cb) {
if (typeof(target_app) == 'function') {
cb = target_app;
target_app = null;
}
Configuration.getAll(function(err, data) {
UX.helpers.dispKeys(data, target_app);
return cb();
});
}

View File

@@ -0,0 +1,335 @@
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var chalk = require('chalk');
var util = require('util');
var fmt = require('../tools/fmt.js');
var fs = require('fs');
var path = require('path');
var cst = require('../../constants.js');
var Promise = require('../tools/promise.min.js');
function pspawn(cmd) {
return new Promise(function(resolve, reject) {
var p_cmd = cmd.split(' ');
var install_instance = spawn(p_cmd[0], p_cmd.splice(1, cmd.length), {
stdio : 'inherit',
env : process.env,
shell : true
});
install_instance.on('close', function(code) {
if (code != 0) {
console.log(chalk.bold.red('Command failed'));
return reject(new Error('Bad cmd return'));
}
return resolve();
});
install_instance.on('error', function (err) {
return reject(err);
});
});
}
function checkDockerSetup() {
return new Promise(function(resolve, reject) {
exec("docker version -f '{{.Client.Version}}'", function(err, stdout, stderr) {
if (err) {
console.error(chalk.red.bold('[Docker access] Error while trying to use docker command'));
if (err.message && err.message.indexOf('Cannot connect to the Docker') > -1) {
console.log();
console.log(chalk.blue.bold('[Solution] Setup Docker to be able to be used without sudo rights:'));
console.log(chalk.bold('$ sudo groupadd docker'));
console.log(chalk.bold('$ sudo usermod -aG docker $USER'));
console.log(chalk.bold('Then LOGOUT and LOGIN your Linux session'));
console.log('Read more: http://bit.ly/29JGdCE');
}
return reject(err);
}
return resolve();
});
});
}
/**
* Switch Dockerfile mode
* check test/programmatic/containerizer.mocha.js
*/
function parseAndSwitch(file_content, main_file, opts) {
var lines = file_content.split('\n');
var mode = opts.mode;
lines[0] = 'FROM keymetrics/pm2:' + opts.node_version;
for (var i = 0; i < lines.length; i++) {
var line = lines[i];
if (['## DISTRIBUTION MODE', '## DEVELOPMENT MODE'].indexOf(line) > -1 ||
i == lines.length - 1) {
lines.splice(i, lines.length);
lines[i] = '## ' + mode.toUpperCase() + ' MODE';
lines[i + 1] = 'ENV NODE_ENV=' + (mode == 'distribution' ? 'production' : mode);
if (mode == 'distribution') {
lines[i + 2] = 'COPY . /var/app';
lines[i + 3] = 'CMD ["pm2-docker", "' + main_file + '", "--env", "production"]';
}
if (mode == 'development') {
lines[i + 2] = 'CMD ["pm2-dev", "' + main_file + '", "--env", "development"]';
}
break;
}
};
lines = lines.join('\n');
return lines;
};
/**
* Replace ENV, COPY and CMD depending on the mode
* @param {String} docker_filepath Dockerfile absolute path
* @param {String} main_file Main file to start in container
* @param {String} mode Mode to switch the Dockerfile
*/
function switchDockerFile(docker_filepath, main_file, opts) {
return new Promise(function(resolve, reject) {
var data = fs.readFileSync(docker_filepath, 'utf8').toString();
if (['distribution', 'development'].indexOf(opts.mode) == -1)
return reject(new Error('Unknown mode'));
var lines = parseAndSwitch(data, main_file, opts)
fs.writeFile(docker_filepath, lines, function(err) {
if (err) return reject(err);
resolve({
Dockerfile_path : docker_filepath,
Dockerfile : lines,
CMD : ''
});
})
});
}
/**
* Generate sample Dockerfile (lib/templates/Dockerfiles)
* @param {String} docker_filepath Dockerfile absolute path
* @param {String} main_file Main file to start in container
* @param {String} mode Mode to switch the Dockerfile
*/
function generateDockerfile(docker_filepath, main_file, opts) {
return new Promise(function(resolve, reject) {
var tpl_file = path.join(cst.TEMPLATE_FOLDER, cst.DOCKERFILE_NODEJS);
var template = fs.readFileSync(tpl_file, {encoding: 'utf8'});
var CMD;
template = parseAndSwitch(template, main_file, opts);
fs.writeFile(docker_filepath, template, function(err) {
if (err) return reject(err);
resolve({
Dockerfile_path : docker_filepath,
Dockerfile : template,
CMD : CMD
});
});
});
}
function handleExit(CLI, opts, mode) {
process.on('SIGINT', function() {
CLI.disconnect();
if (mode != 'distribution')
return false;
exec('docker ps -lq', function(err, stdout, stderr) {
if (err) {
console.error(err);
}
require('vizion').analyze({folder : process.cwd()}, function recur_path(err, meta){
if (!err && meta.revision) {
var commit_id = util.format('#%s(%s) %s',
meta.branch,
meta.revision.slice(0, 5),
meta.comment);
console.log(chalk.bold.magenta('$ docker commit -m "%s" %s %s'),
commit_id,
stdout.replace('\n', ''),
opts.imageName);
}
else
console.log(chalk.bold.magenta('$ docker commit %s %s'), stdout.replace('\n', ''), opts.imageName);
console.log(chalk.bold.magenta('$ docker push %s'), opts.imageName);
});
});
});
}
module.exports = function(CLI) {
CLI.prototype.generateDockerfile = function(script, opts) {
var docker_filepath = path.join(process.cwd(), 'Dockerfile');
var that = this;
fs.stat(docker_filepath, function(err, stat) {
if (err || opts.force == true) {
generateDockerfile(docker_filepath, script, {
mode : 'development'
})
.then(function() {
console.log(chalk.bold('New Dockerfile generated in current folder'));
console.log(chalk.bold('You can now run\n$ pm2 docker:dev <file|config>'));
return that.exitCli(cst.SUCCESS_EXIT);
});
return false;
}
console.log(chalk.red.bold('Dockerfile already exists in this folder, use --force if you want to replace it'));
that.exitCli(cst.ERROR_EXIT);
});
};
CLI.prototype.dockerMode = function(script, opts, mode) {
var promptly = require('promptly');
var self = this;
handleExit(self, opts, mode);
if (mode == 'distribution' && !opts.imageName) {
console.error(chalk.bold.red('--image-name [name] option is missing'));
return self.exitCli(cst.ERROR_EXIT);
}
var template;
var app_path, main_script;
var image_name;
var node_version = opts.nodeVersion ? opts.nodeVersion.split('.')[0] : 'latest';
image_name = opts.imageName || require('crypto').randomBytes(6).toString('hex');
if (script.indexOf('/') > -1) {
app_path = path.join(process.cwd(), path.dirname(script));
main_script = path.basename(script);
}
else {
app_path = process.cwd();
main_script = script;
}
checkDockerSetup()
.then(function() {
/////////////////////////
// Generate Dockerfile //
/////////////////////////
return new Promise(function(resolve, reject) {
var docker_filepath = path.join(process.cwd(), 'Dockerfile');
fs.stat(docker_filepath, function(err, stat) {
if (err) {
// Dockerfile does not exist, generate one
// console.log(chalk.blue.bold('Generating new Dockerfile'));
if (opts.force == true) {
return resolve(generateDockerfile(docker_filepath, main_script, {
node_version : node_version,
mode : mode
}));
}
if (opts.dockerdaemon)
return resolve(generateDockerfile(docker_filepath, main_script, {
node_version : node_version,
mode : mode
}));
promptly.prompt('No Dockerfile in current directory, ok to generate a new one? (y/n)', function(err, value) {
if (value == 'y')
return resolve(generateDockerfile(docker_filepath, main_script, {
node_version : node_version,
mode : mode
}));
else
return self.exitCli(cst.SUCCESS_EXIT);
});
return false;
}
return resolve(switchDockerFile(docker_filepath, main_script, {
node_version : node_version,
mode : mode
}));
});
});
})
.then(function(_template) {
template = _template;
return Promise.resolve();
})
.then(function() {
//////////////////
// Docker build //
//////////////////
var docker_build = util.format('docker build -t %s -f %s',
image_name,
template.Dockerfile_path);
if (opts.fresh == true)
docker_build += ' --no-cache';
docker_build += ' .';
console.log();
fmt.sep();
fmt.title('Building Boot System');
fmt.field('Type', chalk.cyan.bold('Docker'));
fmt.field('Mode', mode);
fmt.field('Image name', image_name);
fmt.field('Docker build command', docker_build);
fmt.field('Dockerfile path', template.Dockerfile_path);
fmt.sep();
return pspawn(docker_build);
})
.then(function() {
////////////////
// Docker run //
////////////////
var docker_run = 'docker run --net host';
if (opts.dockerdaemon == true)
docker_run += ' -d';
if (mode != 'distribution')
docker_run += util.format(' -v %s:/var/app -v /var/app/node_modules', app_path);
docker_run += ' ' + image_name;
var dockerfile_parsed = template.Dockerfile.split('\n');
var base_image = dockerfile_parsed[0];
var run_cmd = dockerfile_parsed[dockerfile_parsed.length - 1];
console.log();
fmt.sep();
fmt.title('Booting');
fmt.field('Type', chalk.cyan.bold('Docker'));
fmt.field('Mode', mode);
fmt.field('Base Image', base_image);
fmt.field('Image Name', image_name);
fmt.field('Docker Command', docker_run);
fmt.field('RUN Command', run_cmd);
fmt.field('CWD', app_path);
fmt.sep();
return pspawn(docker_run);
})
.then(function() {
console.log(chalk.blue.bold('>>> Leaving Docker instance uuid=%s'), image_name);
self.disconnect();
return Promise.resolve();
})
.catch(function(err) {
console.log();
console.log(chalk.grey('Raw error=', err.message));
self.disconnect();
});
};
};
module.exports.generateDockerfile = generateDockerfile;
module.exports.parseAndSwitch = parseAndSwitch;
module.exports.switchDockerFile = switchDockerFile;

459
api.hyungi.net/node_modules/pm2/lib/API/Dashboard.js generated vendored Normal file
View File

@@ -0,0 +1,459 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var os = require('os');
var p = require('path');
var blessed = require('blessed');
var debug = require('debug')('pm2:monit');
var printf = require('sprintf-js').sprintf;
// Total memory
const totalMem = os.totalmem();
var Dashboard = {};
var DEFAULT_PADDING = {
top : 0,
left : 1,
right : 1
};
var WIDTH_LEFT_PANEL = 30;
/**
* Synchronous Dashboard init method
* @method init
* @return this
*/
Dashboard.init = function() {
// Init Screen
this.screen = blessed.screen({
smartCSR: true,
fullUnicode: true
});
this.screen.title = 'PM2 Dashboard';
this.logLines = {}
this.list = blessed.list({
top: '0',
left: '0',
width: WIDTH_LEFT_PANEL + '%',
height: '70%',
padding: 0,
scrollbar: {
ch: ' ',
inverse: false
},
border: {
type: 'line'
},
keys: true,
autoCommandKeys: true,
tags: true,
style: {
selected: {
bg: 'blue',
fg: 'white'
},
scrollbar: {
bg: 'blue',
fg: 'black'
},
fg: 'white',
border: {
fg: 'blue'
},
header: {
fg: 'blue'
}
}
});
this.list.on('select item', (item, i) => {
this.logBox.clearItems()
})
this.logBox = blessed.list({
label: ' Logs ',
top: '0',
left: WIDTH_LEFT_PANEL + '%',
width: 100 - WIDTH_LEFT_PANEL + '%',
height: '70%',
padding: DEFAULT_PADDING,
scrollable: true,
scrollbar: {
ch: ' ',
inverse: false
},
keys: true,
autoCommandKeys: true,
tags: true,
border: {
type: 'line'
},
style: {
fg: 'white',
border: {
fg: 'white'
},
scrollbar: {
bg: 'blue',
fg: 'black'
}
}
});
this.metadataBox = blessed.box({
label: ' Metadata ',
top: '70%',
left: WIDTH_LEFT_PANEL + '%',
width: 100 - WIDTH_LEFT_PANEL + '%',
height: '26%',
padding: DEFAULT_PADDING,
scrollable: true,
scrollbar: {
ch: ' ',
inverse: false
},
keys: true,
autoCommandKeys: true,
tags: true,
border: {
type: 'line'
},
style: {
fg: 'white',
border: {
fg: 'white'
},
scrollbar: {
bg: 'blue',
fg: 'black'
}
}
});
this.metricsBox = blessed.list({
label: ' Custom Metrics ',
top: '70%',
left: '0%',
width: WIDTH_LEFT_PANEL + '%',
height: '26%',
padding: DEFAULT_PADDING,
scrollbar: {
ch: ' ',
inverse: false
},
keys: true,
autoCommandKeys: true,
tags: true,
border: {
type: 'line'
},
style: {
fg: 'white',
border: {
fg: 'white'
},
scrollbar: {
bg: 'blue',
fg: 'black'
}
}
});
this.box4 = blessed.text({
content: ' left/right: switch boards | up/down/mouse: scroll | Ctrl-C: exit{|} {cyan-fg}{bold}To go further check out https://pm2.io/{/} ',
left: '0%',
top: '95%',
width: '100%',
height: '6%',
valign: 'middle',
tags: true,
style: {
fg: 'white'
}
});
this.list.focus();
this.screen.append(this.list);
this.screen.append(this.logBox);
this.screen.append(this.metadataBox);
this.screen.append(this.metricsBox);
this.screen.append(this.box4);
this.list.setLabel(' Process List ');
this.screen.render();
var that = this;
var i = 0;
var boards = ['list', 'logBox', 'metricsBox', 'metadataBox'];
this.screen.key(['left', 'right'], function(ch, key) {
(key.name === 'left') ? i-- : i++;
if (i == 4)
i = 0;
if (i == -1)
i = 3;
that[boards[i]].focus();
that[boards[i]].style.border.fg = 'blue';
if (key.name === 'left') {
if (i == 3)
that[boards[0]].style.border.fg = 'white';
else
that[boards[i + 1]].style.border.fg = 'white';
}
else {
if (i == 0)
that[boards[3]].style.border.fg = 'white';
else
that[boards[i - 1]].style.border.fg = 'white';
}
});
this.screen.key(['escape', 'q', 'C-c'], function(ch, key) {
this.screen.destroy();
process.exit(0);
});
// async refresh of the ui
setInterval(function () {
that.screen.render();
}, 300);
return this;
}
/**
* Refresh dashboard
* @method refresh
* @param {} processes
* @return this
*/
Dashboard.refresh = function(processes) {
debug('Monit refresh');
if(!processes) {
this.list.setItem(0, 'No process available');
return;
}
if (processes.length != this.list.items.length) {
this.list.clearItems();
}
// Total of processes memory
var mem = 0;
processes.forEach(function(proc) {
mem += proc.monit.memory;
})
// Sort process list
processes.sort(function(a, b) {
if (a.pm2_env.name < b.pm2_env.name)
return -1;
if (a.pm2_env.name > b.pm2_env.name)
return 1;
return 0;
});
// Loop to get process infos
for (var i = 0; i < processes.length; i++) {
// Percent of memory use by one process in all pm2 processes
var memPercent = (processes[i].monit.memory / mem) * 100;
// Status of process
var status = processes[i].pm2_env.status == 'online' ? '{green-fg}' : '{red-fg}';
status = status + '{bold}' + processes[i].pm2_env.status + '{/}';
var name = processes[i].pm2_env.name || p.basename(processes[i].pm2_env.pm_exec_path);
// Line of list
var item = printf('[%2s] %s {|} Mem: {bold}{%s-fg}%3d{/} MB CPU: {bold}{%s-fg}%2d{/} %s %s',
processes[i].pm2_env.pm_id,
name,
gradient(memPercent, [255, 0, 0], [0, 255, 0]),
(processes[i].monit.memory / 1048576).toFixed(2),
gradient(processes[i].monit.cpu, [255, 0, 0], [0, 255, 0]),
processes[i].monit.cpu,
"%",
status);
// Check if item exist
if (this.list.getItem(i)) {
this.list.setItem(i, item);
}
else {
this.list.pushItem(item);
}
var proc = processes[this.list.selected];
// render the logBox
let process_id = proc.pm_id
let logs = this.logLines[process_id];
if(typeof(logs) !== "undefined"){
this.logBox.setItems(logs)
if (!this.logBox.focused) {
this.logBox.setScrollPerc(100);
}
}else{
this.logBox.clearItems();
}
this.logBox.setLabel(` ${proc.pm2_env.name} Logs `)
this.metadataBox.setLine(0, 'App Name ' + '{bold}' + proc.pm2_env.name + '{/}');
this.metadataBox.setLine(1, 'Namespace ' + '{bold}' + proc.pm2_env.namespace + '{/}');
this.metadataBox.setLine(2, 'Version ' + '{bold}' + proc.pm2_env.version + '{/}');
this.metadataBox.setLine(3, 'Restarts ' + proc.pm2_env.restart_time);
this.metadataBox.setLine(4, 'Uptime ' + ((proc.pm2_env.pm_uptime && proc.pm2_env.status == 'online') ? timeSince(proc.pm2_env.pm_uptime) : 0));
this.metadataBox.setLine(5, 'Script path ' + proc.pm2_env.pm_exec_path);
this.metadataBox.setLine(6, 'Script args ' + (proc.pm2_env.args ? (typeof proc.pm2_env.args == 'string' ? JSON.parse(proc.pm2_env.args.replace(/'/g, '"')):proc.pm2_env.args).join(' ') : 'N/A'));
this.metadataBox.setLine(7, 'Interpreter ' + proc.pm2_env.exec_interpreter);
this.metadataBox.setLine(8, 'Interpreter args ' + (proc.pm2_env.node_args.length != 0 ? proc.pm2_env.node_args : 'N/A'));
this.metadataBox.setLine(9, 'Exec mode ' + (proc.pm2_env.exec_mode == 'fork_mode' ? '{bold}fork{/}' : '{blue-fg}{bold}cluster{/}'));
this.metadataBox.setLine(10, 'Node.js version ' + proc.pm2_env.node_version);
this.metadataBox.setLine(11, 'watch & reload ' + (proc.pm2_env.watch ? '{green-fg}{bold}✔{/}' : '{red-fg}{bold}✘{/}'));
this.metadataBox.setLine(12, 'Unstable restarts ' + proc.pm2_env.unstable_restarts);
this.metadataBox.setLine(13, 'Comment ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.comment : 'N/A'));
this.metadataBox.setLine(14, 'Revision ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.revision : 'N/A'));
this.metadataBox.setLine(15, 'Branch ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.branch : 'N/A'));
this.metadataBox.setLine(16, 'Remote url ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.url : 'N/A'));
this.metadataBox.deleteLine(17)
this.metadataBox.setLine(17, 'Last update ' + ((proc.pm2_env.versioning) ? proc.pm2_env.versioning.update_time : 'N/A'));
if (Object.keys(proc.pm2_env.axm_monitor).length != this.metricsBox.items.length) {
this.metricsBox.clearItems();
}
var j = 0;
for (var key in proc.pm2_env.axm_monitor) {
var metric_name = proc.pm2_env.axm_monitor[key].hasOwnProperty('value') ? proc.pm2_env.axm_monitor[key].value : proc.pm2_env.axm_monitor[key]
var metric_unit = proc.pm2_env.axm_monitor[key].hasOwnProperty('unit') ? proc.pm2_env.axm_monitor[key].unit : null
var probe = `{bold}${key}{/} {|} ${metric_name}${metric_unit == null ? '' : ' ' + metric_unit}`
if (this.metricsBox.getItem(j)) {
this.metricsBox.setItem(j, probe);
}
else {
this.metricsBox.pushItem(probe);
}
j++;
}
this.screen.render();
}
return this;
}
/**
* Put Log
* @method log
* @param {} data
* @return this
*/
Dashboard.log = function(type, data) {
var that = this;
if(typeof(this.logLines[data.process.pm_id]) == "undefined"){
this.logLines[data.process.pm_id]=[];
}
// Logs colors
switch (type) {
case 'PM2':
var color = '{blue-fg}';
break;
case 'out':
var color = '{green-fg}';
break;
case 'err':
var color = '{red-fg}';
break;
default:
var color = '{white-fg}';
}
var logs = data.data.split('\n')
logs.forEach((log) => {
if (log.length > 0) {
this.logLines[data.process.pm_id].push(color + data.process.name + '{/} > ' + log)
//removing logs if longer than limit
let count = 0;
let max_count = 0;
let leading_process_id = -1;
for(var process_id in this.logLines){
count += this.logLines[process_id].length;
if( this.logLines[process_id].length > max_count){
leading_process_id = process_id;
max_count = this.logLines[process_id].length;
}
}
if (count > 200) {
this.logLines[leading_process_id].shift()
}
}
})
return this;
}
module.exports = Dashboard;
function timeSince(date) {
var seconds = Math.floor((new Date() - date) / 1000);
var interval = Math.floor(seconds / 31536000);
if (interval > 1) {
return interval + 'Y';
}
interval = Math.floor(seconds / 2592000);
if (interval > 1) {
return interval + 'M';
}
interval = Math.floor(seconds / 86400);
if (interval > 1) {
return interval + 'D';
}
interval = Math.floor(seconds / 3600);
if (interval > 1) {
return interval + 'h';
}
interval = Math.floor(seconds / 60);
if (interval > 1) {
return interval + 'm';
}
return Math.floor(seconds) + 's';
}
/* Args :
* p : Percent 0 - 100
* rgb_ : Array of rgb [255, 255, 255]
* Return :
* Hexa #FFFFFF
*/
function gradient(p, rgb_beginning, rgb_end) {
var w = (p / 100) * 2 - 1;
var w1 = (w + 1) / 2.0;
var w2 = 1 - w1;
var rgb = [parseInt(rgb_beginning[0] * w1 + rgb_end[0] * w2),
parseInt(rgb_beginning[1] * w1 + rgb_end[1] * w2),
parseInt(rgb_beginning[2] * w1 + rgb_end[2] * w2)];
return "#" + ((1 << 24) + (rgb[0] << 16) + (rgb[1] << 8) + rgb[2]).toString(16).slice(1);
}

117
api.hyungi.net/node_modules/pm2/lib/API/Deploy.js generated vendored Normal file
View File

@@ -0,0 +1,117 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var fs = require('fs');
var cst = require('../../constants.js');
var Utility = require('../Utility.js');
var Common = require('../Common.js');
function deployHelper() {
console.log('');
console.log('-----> Helper: Deployment with PM2');
console.log('');
console.log(' Generate a sample ecosystem.config.js with the command');
console.log(' $ pm2 ecosystem');
console.log(' Then edit the file depending on your needs');
console.log('');
console.log(' Commands:');
console.log(' setup run remote setup commands');
console.log(' update update deploy to the latest release');
console.log(' revert [n] revert to [n]th last deployment or 1');
console.log(' curr[ent] output current release commit');
console.log(' prev[ious] output previous release commit');
console.log(' exec|run <cmd> execute the given <cmd>');
console.log(' list list previous deploy commits');
console.log(' [ref] deploy to [ref], the "ref" setting, or latest tag');
console.log('');
console.log('');
console.log(' Basic Examples:');
console.log('');
console.log(' First initialize remote production host:');
console.log(' $ pm2 deploy ecosystem.config.js production setup');
console.log('');
console.log(' Then deploy new code:');
console.log(' $ pm2 deploy ecosystem.config.js production');
console.log('');
console.log(' If I want to revert to the previous commit:');
console.log(' $ pm2 deploy ecosystem.config.js production revert 1');
console.log('');
console.log(' Execute a command on remote server:');
console.log(' $ pm2 deploy ecosystem.config.js production exec "pm2 restart all"');
console.log('');
console.log(' PM2 will look by default to the ecosystem.config.js file so you dont need to give the file name:');
console.log(' $ pm2 deploy production');
console.log(' Else you have to tell PM2 the name of your ecosystem file');
console.log('');
console.log(' More examples in https://github.com/Unitech/pm2');
console.log('');
};
module.exports = function(CLI) {
CLI.prototype.deploy = function(file, commands, cb) {
var that = this;
if (file == 'help') {
deployHelper();
return cb ? cb() : that.exitCli(cst.SUCCESS_EXIT);
}
var args = commands.rawArgs;
var env;
args.splice(0, args.indexOf('deploy') + 1);
// Find ecosystem file by default
if (!Common.isConfigFile(file)) {
env = args[0];
var defaultConfigNames = [ ...Common.getConfigFileCandidates('ecosystem'), 'ecosystem.json5', 'package.json'];
file = Utility.whichFileExists(defaultConfigNames);
if (!file) {
Common.printError('Not any default deployment file exists.'+
' Allowed default config file names are: ' + defaultConfigNames.join(', '));
return cb ? cb('Not any default ecosystem file present') : that.exitCli(cst.ERROR_EXIT);
}
}
else
env = args[1];
var json_conf = null;
try {
json_conf = Common.parseConfig(fs.readFileSync(file), file);
} catch (e) {
Common.printError(e);
return cb ? cb(e) : that.exitCli(cst.ERROR_EXIT);
}
if (!env) {
deployHelper();
return cb ? cb() : that.exitCli(cst.SUCCESS_EXIT);
}
if (!json_conf.deploy || !json_conf.deploy[env]) {
Common.printError('%s environment is not defined in %s file', env, file);
return cb ? cb('%s environment is not defined in %s file') : that.exitCli(cst.ERROR_EXIT);
}
if (!json_conf.deploy[env]['post-deploy']) {
json_conf.deploy[env]['post-deploy'] = 'pm2 startOrRestart ' + file + ' --env ' + env;
}
require('pm2-deploy').deployForEnv(json_conf.deploy, env, args, function(err, data) {
if (err) {
Common.printError('Deploy failed');
Common.printError(err.message || err);
return cb ? cb(err) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('--> Success');
return cb ? cb(null, data) : that.exitCli(cst.SUCCESS_EXIT);
});
};
};

775
api.hyungi.net/node_modules/pm2/lib/API/Extra.js generated vendored Normal file
View File

@@ -0,0 +1,775 @@
/***************************
*
* Extra methods
*
**************************/
var cst = require('../../constants.js');
var Common = require('../Common.js');
var UX = require('./UX');
var chalk = require('chalk');
var path = require('path');
var fs = require('fs');
var fmt = require('../tools/fmt.js');
var dayjs = require('dayjs');
var pkg = require('../../package.json');
const copyDirSync = require('../tools/copydirSync.js')
module.exports = function(CLI) {
/**
* Get version of the daemonized PM2
* @method getVersion
* @callback cb
*/
CLI.prototype.getVersion = function(cb) {
var that = this;
that.Client.executeRemote('getVersion', {}, function(err) {
return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
});
};
/**
* Install pm2-sysmonit
*/
CLI.prototype.launchSysMonitoring = function(cb) {
if ((this.pm2_configuration && this.pm2_configuration.sysmonit != 'true') ||
process.env.TRAVIS ||
global.it === 'function' ||
cst.IS_WINDOWS === true)
return cb ? cb(null) : null
var filepath
try {
filepath = path.dirname(require.resolve('pm2-sysmonit'))
} catch(e) {
return cb ? cb(null) : null
}
this.start({
script: filepath
}, {
started_as_module : true
}, (err, res) => {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
return cb ? cb(err) : this.speedList(cst.ERROR_EXIT);
}
return cb ? cb(null) : this.speedList();
});
};
/**
* Show application environment
* @method env
* @callback cb
*/
CLI.prototype.env = function(app_id, cb) {
var procs = []
var printed = 0
this.Client.executeRemote('getMonitorData', {}, (err, list) => {
list.forEach(l => {
if (app_id == l.pm_id) {
printed++
var env = Common.safeExtend({}, l.pm2_env)
Object.keys(env).forEach(key => {
console.log(`${key}: ${chalk.green(env[key])}`)
})
}
})
if (printed == 0) {
Common.err(`Modules with id ${app_id} not found`)
return cb ? cb.apply(null, arguments) : this.exitCli(cst.ERROR_EXIT);
}
return cb ? cb.apply(null, arguments) : this.exitCli(cst.SUCCESS_EXIT);
})
};
/**
* Get version of the daemonized PM2
* @method getVersion
* @callback cb
*/
CLI.prototype.report = function() {
var that = this;
var Log = require('./Log');
that.Client.executeRemote('getReport', {}, function(err, report) {
console.log()
console.log()
console.log()
console.log('```')
fmt.title('PM2 report')
fmt.field('Date', new Date());
fmt.sep();
if (report && !err) {
fmt.title(chalk.bold.blue('Daemon'));
fmt.field('pm2d version', report.pm2_version);
fmt.field('node version', report.node_version);
fmt.field('node path', report.node_path);
fmt.field('argv', report.argv);
fmt.field('argv0', report.argv0);
fmt.field('user', report.user);
fmt.field('uid', report.uid);
fmt.field('gid', report.gid);
fmt.field('uptime', dayjs(new Date()).diff(report.started_at, 'minute') + 'min');
}
fmt.sep();
fmt.title(chalk.bold.blue('CLI'));
fmt.field('local pm2', pkg.version);
fmt.field('node version', process.versions.node);
fmt.field('node path', process.env['_'] || 'not found');
fmt.field('argv', process.argv);
fmt.field('argv0', process.argv0);
fmt.field('user', process.env.USER || process.env.LNAME || process.env.USERNAME);
if (cst.IS_WINDOWS === false && process.geteuid)
fmt.field('uid', process.geteuid());
if (cst.IS_WINDOWS === false && process.getegid)
fmt.field('gid', process.getegid());
var os = require('os');
fmt.sep();
fmt.title(chalk.bold.blue('System info'));
fmt.field('arch', os.arch());
fmt.field('platform', os.platform());
fmt.field('type', os.type());
fmt.field('cpus', os.cpus()[0].model);
fmt.field('cpus nb', Object.keys(os.cpus()).length);
fmt.field('freemem', os.freemem());
fmt.field('totalmem', os.totalmem());
fmt.field('home', os.homedir());
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
fmt.sep();
fmt.title(chalk.bold.blue('PM2 list'));
UX.list(list, that.gl_interact_infos);
fmt.sep();
fmt.title(chalk.bold.blue('Daemon logs'));
Log.tail([{
path : cst.PM2_LOG_FILE_PATH,
app_name : 'PM2',
type : 'PM2'
}], 20, false, function() {
console.log('```')
console.log()
console.log()
console.log(chalk.bold.green('Please copy/paste the above report in your issue on https://github.com/Unitech/pm2/issues'));
console.log()
console.log()
that.exitCli(cst.SUCCESS_EXIT);
});
});
});
};
CLI.prototype.getPID = function(app_name, cb) {
var that = this;
if (typeof(app_name) === 'function') {
cb = app_name;
app_name = null;
}
this.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
var pids = [];
list.forEach(function(app) {
if (!app_name || app_name == app.name)
pids.push(app.pid);
})
if (!cb) {
Common.printOut(pids.join("\n"))
return that.exitCli(cst.SUCCESS_EXIT);
}
return cb(null, pids);
})
}
/**
* Create PM2 memory snapshot
* @method getVersion
* @callback cb
*/
CLI.prototype.profile = function(type, time, cb) {
var that = this;
var dayjs = require('dayjs');
var cmd
if (type == 'cpu') {
cmd = {
ext: '.cpuprofile',
action: 'profileCPU'
}
}
if (type == 'mem') {
cmd = {
ext: '.heapprofile',
action: 'profileMEM'
}
}
var file = path.join(process.cwd(), dayjs().format('dd-HH:mm:ss') + cmd.ext);
time = time || 10000
console.log(`Starting ${cmd.action} profiling for ${time}ms...`)
that.Client.executeRemote(cmd.action, {
pwd : file,
timeout: time
}, function(err) {
if (err) {
console.error(err);
return that.exitCli(1);
}
console.log(`Profile done in ${file}`)
return cb ? cb.apply(null, arguments) : that.exitCli(cst.SUCCESS_EXIT);
});
};
function basicMDHighlight(lines) {
console.log('\n\n+-------------------------------------+')
console.log(chalk.bold('README.md content:'))
lines = lines.split('\n')
var isInner = false
lines.forEach(l => {
if (l.startsWith('#'))
console.log(chalk.bold.green(l))
else if (isInner || l.startsWith('```')) {
if (isInner && l.startsWith('```'))
isInner = false
else if (isInner == false)
isInner = true
console.log(chalk.grey(l))
}
else if (l.startsWith('`'))
console.log(chalk.grey(l))
else
console.log(l)
})
console.log('+-------------------------------------+')
}
/**
* pm2 create command
* create boilerplate of application for fast try
* @method boilerplate
*/
CLI.prototype.boilerplate = function(cb) {
var i = 0
var projects = []
var enquirer = require('enquirer')
const forEach = require('async/forEach')
fs.readdir(path.join(__dirname, '../templates/sample-apps'), (err, items) => {
forEach(items, (app, next) => {
var fp = path.join(__dirname, '../templates/sample-apps', app)
fs.readFile(path.join(fp, 'package.json'), (err, dt) => {
var meta = JSON.parse(dt)
meta.fullpath = fp
meta.folder_name = app
projects.push(meta)
next()
})
}, () => {
const prompt = new enquirer.Select({
name: 'boilerplate',
message: 'Select a boilerplate',
choices: projects.map((p, i) => {
return {
message: `${chalk.bold.blue(p.name)} ${p.description}`,
value: `${i}`
}
})
});
prompt.run()
.then(answer => {
var p = projects[parseInt(answer)]
basicMDHighlight(fs.readFileSync(path.join(p.fullpath, 'README.md')).toString())
console.log(chalk.bold(`>> Project copied inside folder ./${p.folder_name}/\n`))
copyDirSync(p.fullpath, path.join(process.cwd(), p.folder_name));
this.start(path.join(p.fullpath, 'ecosystem.config.js'), {
cwd: p.fullpath
}, () => {
return cb ? cb.apply(null, arguments) : this.speedList(cst.SUCCESS_EXIT);
})
})
.catch(e => {
return cb ? cb.apply(null, arguments) : this.speedList(cst.SUCCESS_EXIT);
});
})
})
}
/**
* Description
* @method sendLineToStdin
*/
CLI.prototype.sendLineToStdin = function(pm_id, line, separator, cb) {
var that = this;
if (!cb && typeof(separator) == 'function') {
cb = separator;
separator = null;
}
var packet = {
pm_id : pm_id,
line : line + (separator || '\n')
};
that.Client.executeRemote('sendLineToStdin', packet, function(err, res) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
return cb ? cb(null, res) : that.speedList();
});
};
/**
* Description
* @method attachToProcess
*/
CLI.prototype.attach = function(pm_id, separator, cb) {
var that = this;
var readline = require('readline');
if (isNaN(pm_id)) {
Common.printError('pm_id must be a process number (not a process name)');
return cb ? cb(Common.retErr('pm_id must be number')) : that.exitCli(cst.ERROR_EXIT);
}
if (typeof(separator) == 'function') {
cb = separator;
separator = null;
}
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rl.on('close', function() {
return cb ? cb() : that.exitCli(cst.SUCCESS_EXIT);
});
that.Client.launchBus(function(err, bus, socket) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
bus.on('log:*', function(type, packet) {
if (packet.process.pm_id !== parseInt(pm_id))
return;
process.stdout.write(packet.data);
});
});
rl.on('line', function(line) {
that.sendLineToStdin(pm_id, line, separator, function() {});
});
};
/**
* Description
* @method sendDataToProcessId
*/
CLI.prototype.sendDataToProcessId = function(proc_id, packet, cb) {
var that = this;
if (typeof proc_id === 'object' && typeof packet === 'function') {
// the proc_id is packet.
cb = packet;
packet = proc_id;
} else {
packet.id = proc_id;
}
that.Client.executeRemote('sendDataToProcessId', packet, function(err, res) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('successfully sent data to process');
return cb ? cb(null, res) : that.speedList();
});
};
/**
* Used for custom actions, allows to trigger function inside an app
* To expose a function you need to use keymetrics/pmx
*
* @method msgProcess
* @param {Object} opts
* @param {String} id process id
* @param {String} action_name function name to trigger
* @param {Object} [opts.opts] object passed as first arg of the function
* @param {String} [uuid] optional unique identifier when logs are emitted
*
*/
CLI.prototype.msgProcess = function(opts, cb) {
var that = this;
that.Client.executeRemote('msgProcess', opts, cb);
};
/**
* Trigger a PMX custom action in target application
* Custom actions allows to interact with an application
*
* @method trigger
* @param {String|Number} pm_id process id or application name
* @param {String} action_name name of the custom action to trigger
* @param {Mixed} params parameter to pass to target action
* @param {Function} cb callback
*/
CLI.prototype.trigger = function(pm_id, action_name, params, cb) {
if (typeof(params) === 'function') {
cb = params;
params = null;
}
var cmd = {
msg : action_name
};
var counter = 0;
var process_wait_count = 0;
var that = this;
var results = [];
if (params)
cmd.opts = params;
if (isNaN(pm_id))
cmd.name = pm_id;
else
cmd.id = pm_id;
this.launchBus(function(err, bus) {
bus.on('axm:reply', function(ret) {
if (ret.process.name == pm_id || ret.process.pm_id == pm_id || ret.process.namespace == pm_id || pm_id == 'all') {
results.push(ret);
Common.printOut('[%s:%s:%s]=%j', ret.process.name, ret.process.pm_id, ret.process.namespace, ret.data.return);
if (++counter == process_wait_count)
return cb ? cb(null, results) : that.exitCli(cst.SUCCESS_EXIT);
}
});
that.msgProcess(cmd, function(err, data) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
if (data.process_count == 0) {
Common.printError('Not any process has received a command (offline or unexistent)');
return cb ? cb(Common.retErr('Unknown process')) : that.exitCli(cst.ERROR_EXIT);
}
process_wait_count = data.process_count;
Common.printOut(chalk.bold('%s processes have received command %s'),
data.process_count, action_name);
});
});
};
/**
* Description
* @method sendSignalToProcessName
* @param {} signal
* @param {} process_name
* @return
*/
CLI.prototype.sendSignalToProcessName = function(signal, process_name, cb) {
var that = this;
that.Client.executeRemote('sendSignalToProcessName', {
signal : signal,
process_name : process_name
}, function(err, list) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('successfully sent signal %s to process name %s', signal, process_name);
return cb ? cb(null, list) : that.speedList();
});
};
/**
* Description
* @method sendSignalToProcessId
* @param {} signal
* @param {} process_id
* @return
*/
CLI.prototype.sendSignalToProcessId = function(signal, process_id, cb) {
var that = this;
that.Client.executeRemote('sendSignalToProcessId', {
signal : signal,
process_id : process_id
}, function(err, list) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('successfully sent signal %s to process id %s', signal, process_id);
return cb ? cb(null, list) : that.speedList();
});
};
/**
* API method to launch a process that will serve directory over http
*/
CLI.prototype.autoinstall = function (cb) {
var filepath = path.resolve(path.dirname(module.filename), '../Sysinfo/ServiceDetection/ServiceDetection.js');
this.start(filepath, (err, res) => {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
return cb ? cb(err) : this.speedList(cst.ERROR_EXIT);
}
return cb ? cb(null) : this.speedList();
});
}
/**
* API method to launch a process that will serve directory over http
*
* @param {Object} opts options
* @param {String} opts.path path to be served
* @param {Number} opts.port port on which http will bind
* @param {Boolean} opts.spa single page app served
* @param {String} opts.basicAuthUsername basic auth username
* @param {String} opts.basicAuthPassword basic auth password
* @param {Object} commander commander object
* @param {Function} cb optional callback
*/
CLI.prototype.serve = function (target_path, port, opts, commander, cb) {
var that = this;
var servePort = process.env.PM2_SERVE_PORT || port || 8080;
var servePath = path.resolve(process.env.PM2_SERVE_PATH || target_path || '.');
var filepath = path.resolve(path.dirname(module.filename), './Serve.js');
if (typeof commander.name === 'string')
opts.name = commander.name
else
opts.name = 'static-page-server-' + servePort
if (!opts.env)
opts.env = {};
opts.env.PM2_SERVE_PORT = servePort;
opts.env.PM2_SERVE_PATH = servePath;
opts.env.PM2_SERVE_SPA = opts.spa;
if (opts.basicAuthUsername && opts.basicAuthPassword) {
opts.env.PM2_SERVE_BASIC_AUTH = 'true';
opts.env.PM2_SERVE_BASIC_AUTH_USERNAME = opts.basicAuthUsername;
opts.env.PM2_SERVE_BASIC_AUTH_PASSWORD = opts.basicAuthPassword;
}
if (opts.monitor) {
opts.env.PM2_SERVE_MONITOR = opts.monitor
}
opts.cwd = servePath;
this.start(filepath, opts, function (err, res) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + 'Error while trying to serve : ' + err.message || err);
return cb ? cb(err) : that.speedList(cst.ERROR_EXIT);
}
Common.printOut(cst.PREFIX_MSG + 'Serving ' + servePath + ' on port ' + servePort);
return cb ? cb(null, res) : that.speedList();
});
}
/**
* Ping daemon - if PM2 daemon not launched, it will launch it
* @method ping
*/
CLI.prototype.ping = function(cb) {
var that = this;
that.Client.executeRemote('ping', {}, function(err, res) {
if (err) {
Common.printError(err);
return cb ? cb(new Error(err)) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut(res);
return cb ? cb(null, res) : that.exitCli(cst.SUCCESS_EXIT);
});
};
/**
* Execute remote command
*/
CLI.prototype.remote = function(command, opts, cb) {
var that = this;
that[command](opts.name, function(err_cmd, ret) {
if (err_cmd)
console.error(err_cmd);
console.log('Command %s finished', command);
return cb(err_cmd, ret);
});
};
/**
* This remote method allows to pass multiple arguments
* to PM2
* It is used for the new scoped PM2 action system
*/
CLI.prototype.remoteV2 = function(command, opts, cb) {
var that = this;
if (that[command].length == 1)
return that[command](cb);
opts.args.push(cb);
return that[command].apply(this, opts.args);
};
/**
* Description
* @method generateSample
* @param {} name
* @return
*/
CLI.prototype.generateSample = function(mode) {
var that = this;
var templatePath;
if (mode == 'simple')
templatePath = path.join(cst.TEMPLATE_FOLDER, cst.APP_CONF_TPL_SIMPLE);
else
templatePath = path.join(cst.TEMPLATE_FOLDER, cst.APP_CONF_TPL);
var sample = fs.readFileSync(templatePath);
var dt = sample.toString();
var f_name = 'ecosystem.config.js';
var pwd = process.env.PWD || process.cwd();
try {
fs.writeFileSync(path.join(pwd, f_name), dt);
} catch (e) {
console.error(e.stack || e);
return that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('File %s generated', path.join(pwd, f_name));
that.exitCli(cst.SUCCESS_EXIT);
};
/**
* Description
* @method dashboard
* @return
*/
CLI.prototype.dashboard = function(cb) {
var that = this;
var Dashboard = require('./Dashboard');
if (cb)
return cb(new Error('Dashboard cant be called programmatically'));
Dashboard.init();
this.Client.launchBus(function (err, bus) {
if (err) {
console.error('Error launchBus: ' + err);
that.exitCli(cst.ERROR_EXIT);
}
bus.on('log:*', function(type, data) {
Dashboard.log(type, data)
})
});
process.on('SIGINT', function() {
this.Client.disconnectBus(function() {
process.exit(cst.SUCCESS_EXIT);
});
});
function refreshDashboard() {
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
console.error('Error retrieving process list: ' + err);
that.exitCli(cst.ERROR_EXIT);
}
Dashboard.refresh(list);
setTimeout(function() {
refreshDashboard();
}, 800);
});
}
refreshDashboard();
};
CLI.prototype.monit = function(cb) {
var that = this;
var Monit = require('./Monit.js');
if (cb) return cb(new Error('Monit cant be called programmatically'));
Monit.init();
function launchMonitor() {
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
console.error('Error retrieving process list: ' + err);
that.exitCli(conf.ERROR_EXIT);
}
Monit.refresh(list);
setTimeout(function() {
launchMonitor();
}, 400);
});
}
launchMonitor();
};
CLI.prototype.inspect = function(app_name, cb) {
const that = this;
this.trigger(app_name, 'internal:inspect', function (err, res) {
if(res && res[0]) {
if (res[0].data.return === '') {
Common.printOut(`Inspect disabled on ${app_name}`);
} else {
Common.printOut(`Inspect enabled on ${app_name} => go to chrome : chrome://inspect !!!`);
}
} else {
Common.printOut(`Unable to activate inspect mode on ${app_name} !!!`);
}
that.exitCli(cst.SUCCESS_EXIT);
});
};
};

View File

@@ -0,0 +1,30 @@
const util = require('util')
const spawn = require('child_process').spawn
const DockerMgmt = {}
module.exports = DockerMgmt
function execDocker(cmd, cb) {
var i = spawn('docker', cmd, {
stdio : 'inherit',
env: process.env,
shell : true
})
i.on('close', cb)
}
DockerMgmt.processCommand = function(PM2, start_id, select_id, action, cb) {
PM2.Client.executeRemote('getSystemData', {}, (err, sys_infos) => {
if (sys_infos.containers && sys_infos.containers.length == 0)
return cb(new Error(`Process ${select_id} not found`))
var container = sys_infos.containers[select_id - start_id - 1]
if (action == 'stopProcessId')
execDocker(['stop', container.id], cb)
if (action == 'deleteProcessId')
execDocker(['rm', container.id], cb)
if (action == 'restartProcessId')
execDocker(['restart', container.id], cb)
})
}

315
api.hyungi.net/node_modules/pm2/lib/API/Log.js generated vendored Normal file
View File

@@ -0,0 +1,315 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var fs = require('fs'),
util = require('util'),
chalk = require('chalk'),
forEachLimit = require('async/forEachLimit'),
dayjs = require('dayjs');
var Log = module.exports = {};
var DEFAULT_PADDING = ' ';
/**
* Tail logs from file stream.
* @param {Object} apps_list
* @param {Number} lines
* @param {Boolean} raw
* @param {Function} callback
* @return
*/
Log.tail = function(apps_list, lines, raw, callback) {
var that = this;
if (lines === 0 || apps_list.length === 0)
return callback && callback();
var count = 0;
var getLastLines = function (filename, lines, callback) {
var chunk = '';
var size = Math.max(0, fs.statSync(filename).size - (lines * 200));
var fd = fs.createReadStream(filename, {start : size});
fd.on('data', function(data) { chunk += data.toString(); });
fd.on('end', function() {
chunk = chunk.split('\n').slice(-(lines+1));
chunk.pop();
callback(chunk);
});
};
apps_list.sort(function(a, b) {
return (fs.existsSync(a.path) ? fs.statSync(a.path).mtime.valueOf() : 0) -
(fs.existsSync(b.path) ? fs.statSync(b.path).mtime.valueOf() : 0);
});
forEachLimit(apps_list, 1, function(app, next) {
if (!fs.existsSync(app.path || ''))
return next();
getLastLines(app.path, lines, function(output) {
console.log(chalk.grey('%s last %d lines:'), app.path, lines);
output.forEach(function(out) {
if (raw)
return app.type === 'err' ? console.error(out) : console.log(out);
if (app.type === 'out')
process.stdout.write(chalk.green(pad(DEFAULT_PADDING, app.app_name) + ' | '));
else if (app.type === 'err')
process.stdout.write(chalk.red(pad(DEFAULT_PADDING, app.app_name) + ' | '));
else
process.stdout.write(chalk.blue(pad(DEFAULT_PADDING, 'PM2') + ' | '));
console.log(out);
});
if (output.length)
process.stdout.write('\n');
next();
});
}, function() {
callback && callback();
});
};
/**
* Stream logs in realtime from the bus eventemitter.
* @param {String} id
* @param {Boolean} raw
* @return
*/
Log.stream = function(Client, id, raw, timestamp, exclusive, highlight) {
var that = this;
Client.launchBus(function(err, bus, socket) {
socket.on('reconnect attempt', function() {
if (global._auto_exit === true) {
if (timestamp)
process.stdout.write(chalk['dim'](chalk.grey(dayjs().format(timestamp) + ' ')));
process.stdout.write(chalk.blue(pad(DEFAULT_PADDING, 'PM2') + ' | ') + '[[[ Target PM2 killed. ]]]');
process.exit(0);
}
});
var min_padding = 3
bus.on('log:*', function(type, packet) {
var isMatchingProcess = id === 'all'
|| packet.process.name == id
|| packet.process.pm_id == id
|| packet.process.namespace == id;
if (!isMatchingProcess)
return;
if ((type === 'out' && exclusive === 'err')
|| (type === 'err' && exclusive === 'out')
|| (type === 'PM2' && exclusive !== false))
return;
var lines;
if (typeof(packet.data) === 'string')
lines = (packet.data || '').split('\n');
else
return;
lines.forEach(function(line) {
if (!line || line.length === 0) return;
if (raw)
return type === 'err' ? process.stderr.write(util.format(line) + '\n') : process.stdout.write(util.format(line) + '\n');
if (timestamp)
process.stdout.write(chalk['dim'](chalk.grey(dayjs().format(timestamp) + ' ')));
var name = packet.process.pm_id + '|' + packet.process.name;
if (name.length > min_padding)
min_padding = name.length + 1
if (type === 'out')
process.stdout.write(chalk.green(pad(' '.repeat(min_padding), name) + ' | '));
else if (type === 'err')
process.stdout.write(chalk.red(pad(' '.repeat(min_padding), name) + ' | '));
else if (!raw && (id === 'all' || id === 'PM2'))
process.stdout.write(chalk.blue(pad(' '.repeat(min_padding), 'PM2') + ' | '));
if (highlight)
process.stdout.write(util.format(line).replace(highlight, chalk.bgBlackBright(highlight)) + '\n');
else
process.stdout.write(util.format(line)+ '\n');
});
});
});
};
Log.devStream = function(Client, id, raw, timestamp, exclusive) {
var that = this;
Client.launchBus(function(err, bus) {
setTimeout(function() {
bus.on('process:event', function(packet) {
if (packet.event == 'online')
console.log(chalk.green('[rundev] App %s restarted'), packet.process.name);
});
}, 1000);
var min_padding = 3
bus.on('log:*', function(type, packet) {
if (id !== 'all'
&& packet.process.name != id
&& packet.process.pm_id != id)
return;
if ((type === 'out' && exclusive === 'err')
|| (type === 'err' && exclusive === 'out')
|| (type === 'PM2' && exclusive !== false))
return;
if (type === 'PM2')
return;
var name = packet.process.pm_id + '|' + packet.process.name;
var lines;
if (typeof(packet.data) === 'string')
lines = (packet.data || '').split('\n');
else
return;
lines.forEach(function(line) {
if (!line || line.length === 0) return;
if (raw)
return process.stdout.write(util.format(line) + '\n');
if (timestamp)
process.stdout.write(chalk['dim'](chalk.grey(dayjs().format(timestamp) + ' ')));
var name = packet.process.name + '-' + packet.process.pm_id;
if (name.length > min_padding)
min_padding = name.length + 1
if (type === 'out')
process.stdout.write(chalk.green(pad(' '.repeat(min_padding), name) + ' | '));
else if (type === 'err')
process.stdout.write(chalk.red(pad(' '.repeat(min_padding), name) + ' | '));
else if (!raw && (id === 'all' || id === 'PM2'))
process.stdout.write(chalk.blue(pad(' '.repeat(min_padding), 'PM2') + ' | '));
process.stdout.write(util.format(line) + '\n');
});
});
});
};
Log.jsonStream = function(Client, id) {
var that = this;
Client.launchBus(function(err, bus) {
if (err) console.error(err);
bus.on('process:event', function(packet) {
process.stdout.write(JSON.stringify({
timestamp : dayjs(packet.at),
type : 'process_event',
status : packet.event,
app_name : packet.process.name
}));
process.stdout.write('\n');
});
bus.on('log:*', function(type, packet) {
if (id !== 'all'
&& packet.process.name != id
&& packet.process.pm_id != id)
return;
if (type === 'PM2')
return;
if (typeof(packet.data) == 'string')
packet.data = packet.data.replace(/(\r\n|\n|\r)/gm,'');
process.stdout.write(JSON.stringify({
message : packet.data,
timestamp : dayjs(packet.at),
type : type,
process_id : packet.process.pm_id,
app_name : packet.process.name
}));
process.stdout.write('\n');
});
});
};
Log.formatStream = function(Client, id, raw, timestamp, exclusive, highlight) {
var that = this;
Client.launchBus(function(err, bus) {
bus.on('log:*', function(type, packet) {
if (id !== 'all'
&& packet.process.name != id
&& packet.process.pm_id != id)
return;
if ((type === 'out' && exclusive === 'err')
|| (type === 'err' && exclusive === 'out')
|| (type === 'PM2' && exclusive !== false))
return;
if (type === 'PM2' && raw)
return;
var name = packet.process.name + '-' + packet.process.pm_id;
var lines;
if (typeof(packet.data) === 'string')
lines = (packet.data || '').split('\n');
else
return;
lines.forEach(function(line) {
if (!line || line.length === 0) return;
if (!raw) {
if (timestamp)
process.stdout.write('timestamp=' + dayjs().format(timestamp) + ' ');
if (packet.process.name === 'PM2')
process.stdout.write('app=pm2 ');
if (packet.process.name !== 'PM2')
process.stdout.write('app=' + packet.process.name + ' id=' + packet.process.pm_id + ' ');
if (type === 'out')
process.stdout.write('type=out ');
else if (type === 'err')
process.stdout.write('type=error ');
}
process.stdout.write('message=');
if (highlight)
process.stdout.write(util.format(line).replace(highlight, chalk.bgBlackBright(highlight)) + '\n');
else
process.stdout.write(util.format(line) + '\n');
});
});
});
};
function pad(pad, str, padLeft) {
if (typeof str === 'undefined')
return pad;
if (padLeft) {
return (pad + str).slice(-pad.length);
} else {
return (str + pad).substring(0, pad.length);
}
}

View File

@@ -0,0 +1,371 @@
var chalk = require('chalk');
var util = require('util');
var fs = require('fs');
var exec = require('child_process').exec;
var path = require('path');
var Log = require('./Log');
var cst = require('../../constants.js');
var Common = require('../Common.js');
module.exports = function(CLI) {
/**
* Description
* @method flush
* @return
*/
CLI.prototype.flush = function(api, cb) {
var that = this;
if (!api) {
Common.printOut(cst.PREFIX_MSG + 'Flushing ' + cst.PM2_LOG_FILE_PATH);
fs.closeSync(fs.openSync(cst.PM2_LOG_FILE_PATH, 'w'));
}
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
list.forEach(function(l) {
if (typeof api == 'undefined') {
Common.printOut(cst.PREFIX_MSG + 'Flushing:');
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
if (l.pm2_env.pm_log_path) {
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
}
fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
}
else if (l.pm2_env.pm_id == api || l.pm2_env.name === api) {
Common.printOut(cst.PREFIX_MSG + 'Flushing:');
if (l.pm2_env.pm_log_path && fs.existsSync(l.pm2_env.pm_log_path)) {
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_log_path);
fs.closeSync(fs.openSync(l.pm2_env.pm_log_path, 'w'));
}
if (l.pm2_env.pm_out_log_path && fs.existsSync(l.pm2_env.pm_out_log_path)) {
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_out_log_path);
fs.closeSync(fs.openSync(l.pm2_env.pm_out_log_path, 'w'));
}
if (l.pm2_env.pm_err_log_path && fs.existsSync(l.pm2_env.pm_err_log_path)) {
Common.printOut(cst.PREFIX_MSG + l.pm2_env.pm_err_log_path);
fs.closeSync(fs.openSync(l.pm2_env.pm_err_log_path, 'w'));
}
}
});
Common.printOut(cst.PREFIX_MSG + 'Logs flushed');
return cb ? cb(null, list) : that.exitCli(cst.SUCCESS_EXIT);
});
};
CLI.prototype.logrotate = function(opts, cb) {
var that = this;
if (process.getuid() != 0) {
return exec('whoami', function(err, stdout, stderr) {
Common.printError(cst.PREFIX_MSG + 'You have to run this command as root. Execute the following command:');
Common.printError(cst.PREFIX_MSG + chalk.grey(' sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' pm2 logrotate -u ' + stdout.trim()));
cb ? cb(Common.retErr('You have to run this with elevated rights')) : that.exitCli(cst.ERROR_EXIT);
});
}
if (!fs.existsSync('/etc/logrotate.d')) {
Common.printError(cst.PREFIX_MSG + '/etc/logrotate.d does not exist we can not copy the default configuration.');
return cb ? cb(Common.retErr('/etc/logrotate.d does not exist')) : that.exitCli(cst.ERROR_EXIT);
}
var templatePath = path.join(cst.TEMPLATE_FOLDER, cst.LOGROTATE_SCRIPT);
Common.printOut(cst.PREFIX_MSG + 'Getting logrorate template ' + templatePath);
var script = fs.readFileSync(templatePath, {encoding: 'utf8'});
var user = opts.user || 'root';
script = script.replace(/%HOME_PATH%/g, cst.PM2_ROOT_PATH)
.replace(/%USER%/g, user);
try {
fs.writeFileSync('/etc/logrotate.d/pm2-'+user, script);
} catch (e) {
console.error(e.stack || e);
}
Common.printOut(cst.PREFIX_MSG + 'Logrotate configuration added to /etc/logrotate.d/pm2');
return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
};
/**
* Description
* @method reloadLogs
* @return
*/
CLI.prototype.reloadLogs = function(cb) {
var that = this;
Common.printOut('Reloading all logs...');
that.Client.executeRemote('reloadLogs', {}, function(err, logs) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
Common.printOut('All logs reloaded');
return cb ? cb(null, logs) : that.exitCli(cst.SUCCESS_EXIT);
});
};
/**
* Description
* @method streamLogs
* @param {String} id
* @param {Number} lines
* @param {Boolean} raw
* @return
*/
CLI.prototype.streamLogs = function(id, lines, raw, timestamp, exclusive, highlight) {
var that = this;
var files_list = [];
// If no argument is given, we stream logs for all running apps
id = id || 'all';
lines = lines !== undefined ? lines : 20;
lines = lines < 0 ? -(lines) : lines;
// Avoid duplicates and check if path is different from '/dev/null'
var pushIfUnique = function(entry) {
var exists = false;
if (entry.path.toLowerCase
&& entry.path.toLowerCase() !== '/dev/null') {
files_list.some(function(file) {
if (file.path === entry.path)
exists = true;
return exists;
});
if (exists)
return;
files_list.push(entry);
}
}
// Get the list of all running apps
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
var regexList = [];
var namespaceList = [];
if (err) {
Common.printError(err);
that.exitCli(cst.ERROR_EXIT);
}
if (lines === 0)
return Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
Common.printOut(chalk.bold.grey(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
// Populate the array `files_list` with the paths of all files we need to tail
list.forEach(function(proc) {
if (proc.pm2_env && (id === 'all' ||
proc.pm2_env.name == id ||
proc.pm2_env.pm_id == id)) {
if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
pushIfUnique({
path : proc.pm2_env.pm_out_log_path,
app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'out'});
if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
pushIfUnique({
path : proc.pm2_env.pm_err_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'err'
});
} else if(proc.pm2_env && proc.pm2_env.namespace == id) {
if(namespaceList.indexOf(proc.pm2_env.name) === -1) {
namespaceList.push(proc.pm2_env.name)
}
if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
pushIfUnique({
path : proc.pm2_env.pm_out_log_path,
app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'out'});
if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
pushIfUnique({
path : proc.pm2_env.pm_err_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'err'
});
}
// Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
var regex = new RegExp(id.replace(/\//g, ''));
if(regex.test(proc.pm2_env.name)) {
if(regexList.indexOf(proc.pm2_env.name) === -1) {
regexList.push(proc.pm2_env.name);
}
if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
pushIfUnique({
path : proc.pm2_env.pm_out_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'out'});
if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
pushIfUnique({
path : proc.pm2_env.pm_err_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'err'
});
}
}
});
//for fixing issue https://github.com/Unitech/pm2/issues/3506
/* if (files_list && files_list.length == 0) {
Common.printError(cst.PREFIX_MSG_ERR + 'No file to stream for app [%s], exiting.', id);
return process.exit(cst.ERROR_EXIT);
}*/
if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
Log.tail([{
path : cst.PM2_LOG_FILE_PATH,
app_name : 'PM2',
type : 'PM2'
}], lines, raw, function() {
Log.tail(files_list, lines, raw, function() {
Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
});
});
}
else {
Log.tail(files_list, lines, raw, function() {
if(regexList.length > 0) {
regexList.forEach(function(id) {
Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
})
}
else if(namespaceList.length > 0) {
namespaceList.forEach(function(id) {
Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
})
}
else {
Log.stream(that.Client, id, raw, timestamp, exclusive, highlight);
}
});
}
});
};
/**
* Description
* @method printLogs
* @param {String} id
* @param {Number} lines
* @param {Boolean} raw
* @return
*/
CLI.prototype.printLogs = function(id, lines, raw, timestamp, exclusive) {
var that = this;
var files_list = [];
// If no argument is given, we stream logs for all running apps
id = id || 'all';
lines = lines !== undefined ? lines : 20;
lines = lines < 0 ? -(lines) : lines;
// Avoid duplicates and check if path is different from '/dev/null'
var pushIfUnique = function(entry) {
var exists = false;
if (entry.path.toLowerCase
&& entry.path.toLowerCase() !== '/dev/null') {
files_list.some(function(file) {
if (file.path === entry.path)
exists = true;
return exists;
});
if (exists)
return;
files_list.push(entry);
}
}
// Get the list of all running apps
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError(err);
that.exitCli(cst.ERROR_EXIT);
}
if (lines <= 0) {
return that.exitCli(cst.SUCCESS_EXIT)
}
Common.printOut(chalk.bold.grey(util.format.call(this, '[TAILING] Tailing last %d lines for [%s] process%s (change the value with --lines option)', lines, id, id === 'all' ? 'es' : '')));
// Populate the array `files_list` with the paths of all files we need to tail
list.forEach(function(proc) {
if (proc.pm2_env && (id === 'all' ||
proc.pm2_env.name == id ||
proc.pm2_env.pm_id == id)) {
if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
pushIfUnique({
path : proc.pm2_env.pm_out_log_path,
app_name :proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'out'});
if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
pushIfUnique({
path : proc.pm2_env.pm_err_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'err'
});
}
// Populate the array `files_list` with the paths of all files we need to tail, when log in put is a regex
else if(proc.pm2_env && (isNaN(id) && id[0] === '/' && id[id.length - 1] === '/')) {
var regex = new RegExp(id.replace(/\//g, ''));
if(regex.test(proc.pm2_env.name)) {
if (proc.pm2_env.pm_out_log_path && exclusive !== 'err')
pushIfUnique({
path : proc.pm2_env.pm_out_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'out'});
if (proc.pm2_env.pm_err_log_path && exclusive !== 'out')
pushIfUnique({
path : proc.pm2_env.pm_err_log_path,
app_name : proc.pm2_env.pm_id + '|' + proc.pm2_env.name,
type : 'err'
});
}
}
});
if (!raw && (id === 'all' || id === 'PM2') && exclusive === false) {
Log.tail([{
path : cst.PM2_LOG_FILE_PATH,
app_name : 'PM2',
type : 'PM2'
}], lines, raw, function() {
Log.tail(files_list, lines, raw, function() {
that.exitCli(cst.SUCCESS_EXIT);
});
});
}
else {
Log.tail(files_list, lines, raw, function() {
that.exitCli(cst.SUCCESS_EXIT);
});
}
});
};
};

View File

@@ -0,0 +1,122 @@
var path = require('path');
var fs = require('fs');
var os = require('os');
var spawn = require('child_process').spawn;
var chalk = require('chalk');
var parallel = require('async/parallel');
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var Utility = require('../../Utility.js');
var readline = require('readline')
var INTERNAL_MODULES = {
'deep-monitoring': {
dependencies: [{name: 'v8-profiler-node8'}, {name: 'gc-stats'}, {name: 'event-loop-inspector'}]
},
'gc-stats': {name: 'gc-stats'},
'event-loop-inspector': {name: 'event-loop-inspector'},
'v8-profiler': {name: 'v8-profiler-node8'},
'profiler': {name: 'v8-profiler-node8'},
'typescript': {dependencies: [{name: 'typescript'}, {name: 'ts-node@latest'}]},
'livescript': {name: 'livescript'},
'coffee-script': {name: 'coffee-script', message: 'Coffeescript v1 support'},
'coffeescript': {name: 'coffeescript', message: 'Coffeescript v2 support'}
};
module.exports = {
install,
INTERNAL_MODULES,
installMultipleModules
}
function install(module, cb, verbose) {
if (!module || !module.name || module.name.length === 0) {
return cb(new Error('No module name !'));
}
if (typeof verbose === 'undefined') {
verbose = true;
}
installLangModule(module.name, function (err) {
var display = module.message || module.name;
if (err) {
if (verbose) { Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green(display + ' installation has FAILED (checkout previous logs)')); }
return cb(err);
}
if (verbose) { Common.printOut(cst.PREFIX_MSG + chalk.bold.green(display + ' ENABLED')); }
return cb();
});
}
function installMultipleModules(modules, cb, post_install) {
var functionList = [];
for (var i = 0; i < modules.length; i++) {
functionList.push((function (index) {
return function (callback) {
var module = modules[index];
if (typeof modules[index] === 'string') {
module = {name: modules[index]};
}
install(module, function ($post_install, err, $index, $modules) {
try {
var install_instance = spawn(post_install[modules[index]], {
stdio : 'inherit',
windowsHide: true,
env: process.env,
shell : true,
cwd : process.cwd()
});
Common.printOut(cst.PREFIX_MSG_MOD + 'Running configuraton script.');
}
catch(e)
{
Common.printOut(cst.PREFIX_MSG_MOD + 'No configuraton script found.');
}
callback(null, { module: module, err: err });
}, false);
};
})(i));
}
parallel(functionList, function (err, results) {
for (var i = 0; i < results.length; i++) {
var display = results[i].module.message || results[i].module.name;
if (results[i].err) {
err = results[i].err;
Common.printError(cst.PREFIX_MSG_MOD_ERR + chalk.bold.green(display + ' installation has FAILED (checkout previous logs)'));
} else {
Common.printOut(cst.PREFIX_MSG + chalk.bold.green(display + ' ENABLED'));
}
}
if(cb) cb(err);
});
};
function installLangModule(module_name, cb) {
var node_module_path = path.resolve(path.join(__dirname, '../../../'));
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');
var install_instance = spawn(cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error'], {
stdio : 'inherit',
env: process.env,
shell : true,
cwd : node_module_path
});
install_instance.on('close', function(code) {
if (code > 0)
return cb(new Error('Module install failed'));
return cb(null);
});
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
};

View File

@@ -0,0 +1,148 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var path = require('path');
var eachLimit = require('async/eachLimit');
var forEachLimit = require('async/forEachLimit');
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var NPM = require('./NPM.js')
var TAR = require('./TAR.js')
var LOCAL = require('./LOCAL.js')
var Modularizer = module.exports = {};
/**
* PM2 Module System.
*/
Modularizer.install = function (CLI, module_name, opts, cb) {
module_name = module_name.replace(/[;`|]/g, "");
if (typeof(opts) == 'function') {
cb = opts;
opts = {};
}
if (LOCAL.INTERNAL_MODULES.hasOwnProperty(module_name)) {
Common.logMod(`Adding dependency ${module_name} to PM2 Runtime`);
var currentModule = LOCAL.INTERNAL_MODULES[module_name];
if (currentModule && currentModule.hasOwnProperty('dependencies')) {
LOCAL.installMultipleModules(currentModule.dependencies, cb);
} else {
LOCAL.install(currentModule, cb);
}
}
else if (module_name == '.') {
Common.logMod(`Installing local NPM module`);
return NPM.localStart(CLI, opts, cb)
}
else if (opts.tarball || /\.tar\.gz$/i.test(module_name)) {
Common.logMod(`Installing TAR module`);
TAR.install(CLI, module_name, opts, cb)
}
else {
Common.logMod(`Installing NPM ${module_name} module`);
NPM.install(CLI, module_name, opts, cb)
}
};
/**
* Launch All Modules
* Used PM2 at startup
*/
Modularizer.launchModules = function(CLI, cb) {
var modules = Modularizer.listModules();
if (!modules) return cb();
// 1#
function launchNPMModules(cb) {
if (!modules.npm_modules) return launchTARModules(cb)
eachLimit(Object.keys(modules.npm_modules), 1, function(module_name, next) {
NPM.start(CLI, modules, module_name, next)
}, function() {
launchTARModules(cb)
});
}
// 2#
function launchTARModules(cb) {
if (!modules.tar_modules) return cb()
eachLimit(Object.keys(modules.tar_modules), 1, function(module_name, next) {
TAR.start(CLI, module_name, next)
}, function() {
return cb ? cb(null) : false;
});
}
launchNPMModules(cb)
}
Modularizer.package = function(CLI, module_path, cb) {
var fullpath = process.cwd()
if (module_path)
fullpath = require('path').resolve(module_path)
TAR.package(fullpath, process.cwd(), cb)
}
/**
* Uninstall module
*/
Modularizer.uninstall = function(CLI, module_name, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Uninstalling module ' + module_name);
var modules_list = Modularizer.listModules();
if (module_name == 'all') {
if (!modules_list) return cb();
return forEachLimit(Object.keys(modules_list.npm_modules), 1, function(module_name, next) {
NPM.uninstall(CLI, module_name, next)
}, () => {
forEachLimit(Object.keys(modules_list.tar_modules), 1, function(module_name, next) {
TAR.uninstall(CLI, module_name, next)
}, cb)
});
}
if (modules_list.npm_modules[module_name]) {
NPM.uninstall(CLI, module_name, cb)
} else if (modules_list.tar_modules[module_name]) {
TAR.uninstall(CLI, module_name, cb)
}
else {
Common.errMod('Unknown module')
CLI.exitCli(1)
}
};
/**
* List modules based on modules present in ~/.pm2/modules/ folder
*/
Modularizer.listModules = function() {
return {
npm_modules: Configuration.getSync(cst.MODULE_CONF_PREFIX) || {},
tar_modules: Configuration.getSync(cst.MODULE_CONF_PREFIX_TAR) || {}
}
};
Modularizer.getAdditionalConf = function(app_name) {
return NPM.getModuleConf(app_name)
};
Modularizer.publish = function(PM2, folder, opts, cb) {
if (opts.npm == true) {
NPM.publish(opts, cb)
}
else {
TAR.publish(PM2, folder, cb)
}
};
Modularizer.generateSample = function(app_name, cb) {
NPM.generateSample(app_name, cb)
};

437
api.hyungi.net/node_modules/pm2/lib/API/Modules/NPM.js generated vendored Normal file
View File

@@ -0,0 +1,437 @@
const path = require('path');
const fs = require('fs');
const os = require('os');
const spawn = require('child_process').spawn;
const chalk = require('chalk');
const readline = require('readline')
const which = require('../../tools/which.js')
const sexec = require('../../tools/sexec.js')
const copydirSync = require('../../tools/copydirSync.js')
const deleteFolderRecursive = require('../../tools/deleteFolderRecursive.js')
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var Utility = require('../../Utility.js');
module.exports = {
install,
uninstall,
start,
publish,
generateSample,
localStart,
getModuleConf
}
/**
* PM2 Module System.
* Features:
* - Installed modules are listed separately from user applications
* - Always ON, a module is always up along PM2, to stop it, you need to uninstall it
* - Install a runnable module from NPM/Github/HTTP (require a package.json only)
* - Some modules add internal PM2 depencencies (like typescript, profiling...)
* - Internally it uses NPM install (https://docs.npmjs.com/cli/install)
* - Auto discover script to launch (first it checks the apps field, then bin and finally main attr)
* - Generate sample module via pm2 module:generate <module_name>
*/
function localStart(PM2, opts, cb) {
var proc_path = '',
cmd = '',
conf = {};
Common.printOut(cst.PREFIX_MSG_MOD + 'Installing local module in DEVELOPMENT MODE with WATCH auto restart');
proc_path = process.cwd();
cmd = path.join(proc_path, cst.DEFAULT_MODULE_JSON);
Common.extend(opts, {
cmd : cmd,
development_mode : true,
proc_path : proc_path
});
return StartModule(PM2, opts, function(err, dt) {
if (err) return cb(err);
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
return cb(null, dt);
});
}
function generateSample(app_name, cb) {
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
function samplize(module_name) {
var cmd1 = 'git clone https://github.com/pm2-hive/sample-module.git ' + module_name + '; cd ' + module_name + '; rm -rf .git';
var cmd2 = 'cd ' + module_name + ' ; sed -i "s:sample-module:'+ module_name +':g" package.json';
var cmd3 = 'cd ' + module_name + ' ; npm install';
Common.printOut(cst.PREFIX_MSG_MOD + 'Getting sample app');
sexec(cmd1, function(err) {
if (err) Common.printError(cst.PREFIX_MSG_MOD_ERR + err.message);
sexec(cmd2, function(err) {
console.log('');
sexec(cmd3, function(err) {
console.log('');
Common.printOut(cst.PREFIX_MSG_MOD + 'Module sample created in folder: ', path.join(process.cwd(), module_name));
console.log('');
Common.printOut('Start module in development mode:');
Common.printOut('$ cd ' + module_name + '/');
Common.printOut('$ pm2 install . ');
console.log('');
Common.printOut('Module Log: ');
Common.printOut('$ pm2 logs ' + module_name);
console.log('');
Common.printOut('Uninstall module: ');
Common.printOut('$ pm2 uninstall ' + module_name);
console.log('');
Common.printOut('Force restart: ');
Common.printOut('$ pm2 restart ' + module_name);
return cb ? cb() : false;
});
});
});
}
if (app_name) return samplize(app_name);
rl.question(cst.PREFIX_MSG_MOD + "Module name: ", function(module_name) {
samplize(module_name);
});
}
function publish(opts, cb) {
var rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
var semver = require('semver');
var package_file = path.join(process.cwd(), 'package.json');
var package_json = require(package_file);
package_json.version = semver.inc(package_json.version, 'minor');
Common.printOut(cst.PREFIX_MSG_MOD + 'Incrementing module to: %s@%s',
package_json.name,
package_json.version);
rl.question("Write & Publish? [Y/N]", function(answer) {
if (answer != "Y")
return cb();
fs.writeFile(package_file, JSON.stringify(package_json, null, 2), function(err, data) {
if (err) return cb(err);
Common.printOut(cst.PREFIX_MSG_MOD + 'Publishing module - %s@%s',
package_json.name,
package_json.version);
sexec('npm publish', function(code) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module - %s@%s successfully published',
package_json.name,
package_json.version);
Common.printOut(cst.PREFIX_MSG_MOD + 'Pushing module on Git');
sexec('git add . ; git commit -m "' + package_json.version + '"; git push origin master', function(code) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Installable with pm2 install %s', package_json.name);
return cb(null, package_json);
});
});
});
});
}
function moduleExistInLocalDB(CLI, module_name, cb) {
var modules = Configuration.getSync(cst.MODULE_CONF_PREFIX);
if (!modules) return cb(false);
var module_name_only = Utility.getCanonicModuleName(module_name)
modules = Object.keys(modules);
return cb(modules.indexOf(module_name_only) > -1 ? true : false);
};
function install(CLI, module_name, opts, cb) {
moduleExistInLocalDB(CLI, module_name, function (exists) {
if (exists) {
Common.logMod('Module already installed. Updating.');
Rollback.backup(module_name);
return uninstall(CLI, module_name, function () {
return continueInstall(CLI, module_name, opts, cb);
});
}
return continueInstall(CLI, module_name, opts, cb);
})
}
// Builtin Node Switch
function getNPMCommandLine(module_name, install_path) {
if (which('npm')) {
return spawn.bind(this, cst.IS_WINDOWS ? 'npm.cmd' : 'npm', ['install', module_name, '--loglevel=error', '--prefix', `"${install_path}"` ], {
stdio : 'inherit',
env: process.env,
windowsHide: true,
shell : true
})
}
else {
return spawn.bind(this, cst.BUILTIN_NODE_PATH, [cst.BUILTIN_NPM_PATH, 'install', module_name, '--loglevel=error', '--prefix', `"${install_path}"`], {
stdio : 'inherit',
env: process.env,
windowsHide: true,
shell : true
})
}
}
function continueInstall(CLI, module_name, opts, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Calling ' + chalk.bold.red('[NPM]') + ' to install ' + module_name + ' ...');
var canonic_module_name = Utility.getCanonicModuleName(module_name);
var install_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);
require('mkdirp')(install_path)
.then(function() {
process.chdir(os.homedir());
var install_instance = getNPMCommandLine(module_name, install_path)();
install_instance.on('close', finalizeInstall);
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
});
function finalizeInstall(code) {
if (code != 0) {
// If install has failed, revert to previous module version
return Rollback.revert(CLI, module_name, function() {
return cb(new Error('Installation failed via NPM, module has been restored to prev version'));
});
}
Common.printOut(cst.PREFIX_MSG_MOD + 'Module downloaded');
var proc_path = path.join(install_path, 'node_modules', canonic_module_name);
var package_json_path = path.join(proc_path, 'package.json');
// Append default configuration to module configuration
try {
var conf = JSON.parse(fs.readFileSync(package_json_path).toString()).config;
if (conf) {
Object.keys(conf).forEach(function(key) {
Configuration.setSyncIfNotExist(canonic_module_name + ':' + key, conf[key]);
});
}
} catch(e) {
Common.printError(e);
}
opts = Common.extend(opts, {
cmd : package_json_path,
development_mode : false,
proc_path : proc_path
});
Configuration.set(cst.MODULE_CONF_PREFIX + ':' + canonic_module_name, {
uid : opts.uid,
gid : opts.gid
}, function(err, data) {
if (err) return cb(err);
StartModule(CLI, opts, function(err, dt) {
if (err) return cb(err);
if (process.env.PM2_PROGRAMMATIC === 'true')
return cb(null, dt);
CLI.conf(canonic_module_name, function() {
Common.printOut(cst.PREFIX_MSG_MOD + 'Module successfully installed and launched');
Common.printOut(cst.PREFIX_MSG_MOD + 'Checkout module options: `$ pm2 conf`');
return cb(null, dt);
});
});
});
}
}
function start(PM2, modules, module_name, cb) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Starting NPM module ' + module_name);
var install_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
var proc_path = path.join(install_path, 'node_modules', module_name);
var package_json_path = path.join(proc_path, 'package.json');
var opts = {};
// Merge with embedded configuration inside module_conf (uid, gid)
Common.extend(opts, modules[module_name]);
// Merge meta data to start module properly
Common.extend(opts, {
// package.json path
cmd : package_json_path,
// starting mode
development_mode : false,
// process cwd
proc_path : proc_path
});
StartModule(PM2, opts, function(err, dt) {
if (err) console.error(err);
return cb();
})
}
function uninstall(CLI, module_name, cb) {
var module_name_only = Utility.getCanonicModuleName(module_name)
var proc_path = path.join(cst.DEFAULT_MODULE_PATH, module_name_only);
Configuration.unsetSync(cst.MODULE_CONF_PREFIX + ':' + module_name_only);
CLI.deleteModule(module_name_only, function(err, data) {
console.log('Deleting', proc_path)
if (module_name != '.' && proc_path.includes('modules') === true) {
deleteFolderRecursive(proc_path)
}
if (err) {
Common.printError(err);
return cb(err);
}
return cb(null, data);
});
}
function getModuleConf(app_name) {
if (!app_name) throw new Error('No app_name defined');
var module_conf = Configuration.getAllSync();
var additional_env = {};
if (!module_conf[app_name]) {
additional_env = {};
additional_env[app_name] = {};
}
else {
additional_env = Common.clone(module_conf[app_name]);
additional_env[app_name] = JSON.stringify(module_conf[app_name]);
}
return additional_env;
}
function StartModule(CLI, opts, cb) {
if (!opts.cmd && !opts.package) throw new Error('module package.json not defined');
if (!opts.development_mode) opts.development_mode = false;
var package_json = require(opts.cmd || opts.package);
/**
* Script file detection
* 1- *apps* field (default pm2 json configuration)
* 2- *bin* field
* 3- *main* field
*/
if (!package_json.apps && !package_json.pm2) {
package_json.apps = {};
if (package_json.bin) {
var bin = Object.keys(package_json.bin)[0];
package_json.apps.script = package_json.bin[bin];
}
else if (package_json.main) {
package_json.apps.script = package_json.main;
}
}
Common.extend(opts, {
cwd : opts.proc_path,
watch : opts.development_mode,
force_name : package_json.name,
started_as_module : true
});
// Start the module
CLI.start(package_json, opts, function(err, data) {
if (err) return cb(err);
if (opts.safe) {
Common.printOut(cst.PREFIX_MSG_MOD + 'Monitoring module behavior for potential issue (5secs...)');
var time = typeof(opts.safe) == 'boolean' ? 3000 : parseInt(opts.safe);
return setTimeout(function() {
CLI.describe(package_json.name, function(err, apps) {
if (err || apps[0].pm2_env.restart_time > 2) {
return Rollback.revert(CLI, package_json.name, function() {
return cb(new Error('New Module is instable, restored to previous version'));
});
}
return cb(null, data);
});
}, time);
}
return cb(null, data);
});
};
var Rollback = {
revert : function(CLI, module_name, cb) {
var canonic_module_name = Utility.getCanonicModuleName(module_name);
var backup_path = path.join(require('os').tmpdir(), canonic_module_name);
var module_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);
try {
fs.statSync(backup_path)
} catch(e) {
return cb(new Error('no backup found'));
}
Common.printOut(cst.PREFIX_MSG_MOD + chalk.bold.red('[[[[[ Module installation failure! ]]]]]'));
Common.printOut(cst.PREFIX_MSG_MOD + chalk.bold.red('[RESTORING TO PREVIOUS VERSION]'));
CLI.deleteModule(canonic_module_name, function() {
// Delete failing module
if (module_name.includes('modules') === true)
deleteFolderRecursive(module_path)
// Restore working version
copydirSync(backup_path, path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name));
var proc_path = path.join(module_path, 'node_modules', canonic_module_name);
var package_json_path = path.join(proc_path, 'package.json');
// Start module
StartModule(CLI, {
cmd : package_json_path,
development_mode : false,
proc_path : proc_path
}, cb);
});
},
backup : function(module_name) {
// Backup current module
var tmpdir = require('os').tmpdir();
var canonic_module_name = Utility.getCanonicModuleName(module_name);
var module_path = path.join(cst.DEFAULT_MODULE_PATH, canonic_module_name);
copydirSync(module_path, path.join(tmpdir, canonic_module_name));
}
}

362
api.hyungi.net/node_modules/pm2/lib/API/Modules/TAR.js generated vendored Normal file
View File

@@ -0,0 +1,362 @@
var Configuration = require('../../Configuration.js');
var cst = require('../../../constants.js');
var Common = require('../../Common');
var forEachLimit = require('async/forEachLimit');
const sexec = require('../../tools/sexec.js');
const deleteFolderRecursive = require('../../tools/deleteFolderRecursive.js');
var path = require('path');
var fs = require('fs');
var os = require('os');
var spawn = require('child_process').spawn;
var exec = require('child_process').exec;
var execSync = require('child_process').execSync;
module.exports = {
install,
uninstall,
start,
publish,
packager
}
/**
* Module management to manage tarball packages
*
* pm2 install http.tar.gz
* pm2 uninstall http
*
* - the first and only folder in the tarball must be called module (tar zcvf http module/)
* - a package.json must be present with attribute "name", "version" and "pm2" to declare apps to run
*/
function install(PM2, module_filepath, opts, cb) {
// Remote file retrieval
if (module_filepath.includes('http') === true) {
var target_file = module_filepath.split('/').pop()
var target_filepath = path.join(os.tmpdir(), target_file)
opts.install_url = module_filepath
return retrieveRemote(module_filepath, target_filepath, (err) => {
if (err) {
Common.errMod(err)
process.exit(1)
}
installLocal(PM2, target_filepath, opts, cb)
})
}
// Local install
installLocal(PM2, module_filepath, opts, cb)
}
function retrieveRemote(url, dest, cb) {
Common.logMod(`Retrieving remote package ${url}...`)
var wget = spawn('wget', [url, '-O', dest, '-q'], {
stdio : 'inherit',
env: process.env,
windowsHide: true,
shell : true
})
wget.on('error', (err) => {
console.error(err.stack || err)
})
wget.on('close', (code) => {
if (code !== 0)
return cb(new Error('Could not download'))
return cb(null)
})
}
function installLocal(PM2, module_filepath, opts, cb) {
Common.logMod(`Installing package ${module_filepath}`)
// Get module name by unpacking the module/package.json only and read the name attribute
getModuleName(module_filepath, function(err, module_name) {
if (err) return cb(err)
Common.logMod(`Module name is ${module_name}`)
Common.logMod(`Depackaging module...`)
var install_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
require('mkdirp').sync(install_path)
var install_instance = spawn('tar', ['zxf', module_filepath, '-C', install_path, '--strip-components 1'], {
stdio : 'inherit',
env: process.env,
shell : true
})
install_instance.on('close', function(code) {
Common.logMod(`Module depackaged in ${install_path}`)
if (code == 0)
return runInstall(PM2, install_path, module_name, opts, cb)
return PM2.exitCli(1)
});
install_instance.on('error', function (err) {
console.error(err.stack || err);
});
})
}
function deleteModulePath(module_name) {
var sanitized = module_name.replace(/\./g, '')
deleteFolderRecursive(path.join(cst.DEFAULT_MODULE_PATH, module_name));
}
function runInstall(PM2, target_path, module_name, opts, cb) {
var config_file = path.join(target_path, 'package.json')
var conf
try {
conf = require(config_file)
module_name = conf.name
} catch(e) {
Common.errMod(new Error('Cannot find package.json file with name attribute at least'));
}
// Force with the name in the package.json
opts.started_as_module = true
opts.cwd = target_path
if (needPrefix(conf))
opts.name_prefix = module_name
if (opts.install) {
Common.logMod(`Running YARN install...`)
sexec(`cd ${target_path} ; yarn install`, {silent: false}, function(code) {
// Start apps under "apps" or "pm2" attribute
Common.logMod(`Starting ${target_path}`)
PM2.start(conf, opts, function(err, data) {
if (err) return cb(err)
Configuration.setSync(`${cst.MODULE_CONF_PREFIX_TAR}:${module_name}`, {
source: 'tarball',
install_url: opts.install_url,
installed_at: Date.now()
})
Common.logMod(`Module INSTALLED and STARTED`)
return cb(null, 'Module installed & Started')
})
})
}
else {
PM2.start(conf, opts, function(err, data) {
if (err) return cb(err)
Configuration.setSync(`${cst.MODULE_CONF_PREFIX_TAR}:${module_name}`, {
source: 'tarball',
install_url: opts.install_url,
installed_at: Date.now()
})
Common.logMod(`Module INSTALLED and STARTED`)
return cb(null, 'Module installed & Started')
})
}
}
function start(PM2, module_name, cb) {
var module_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
Common.printOut(cst.PREFIX_MSG_MOD + 'Starting TAR module ' + module_name);
var package_json_path = path.join(module_path, 'package.json');
var module_conf = Configuration.getSync(`${cst.MODULE_CONF_PREFIX_TAR}:${module_name}`)
try {
var conf = require(package_json_path)
} catch(e) {
Common.printError(`Could not find package.json as ${package_json_path}`)
return cb()
}
var opts = {};
opts.started_as_module = true
opts.cwd = module_path
if (module_conf.install_url)
opts.install_url = module_conf.install_url
if (needPrefix(conf))
opts.name_prefix = module_name
PM2.start(conf, opts, function(err, data) {
if (err) {
Common.printError(`Could not start ${module_name} ${module_path}`)
return cb()
}
Common.printOut(`${cst.PREFIX_MSG_MOD} Module ${module_name} STARTED`)
return cb();
})
}
/**
* Retrieve from module package.json the name of each application
* delete process and delete folder
*/
function uninstall(PM2, module_name, cb) {
var module_path = path.join(cst.DEFAULT_MODULE_PATH, module_name);
Common.logMod(`Removing ${module_name} from auto startup`)
try {
var pkg = require(path.join(module_path, 'package.json'))
} catch(e) {
Common.errMod('Could not retrieve module package.json');
return cb(e)
}
var apps = pkg.apps || pkg.pm2
apps = [].concat(apps);
/**
* Some time a module can have multiple processes
*/
forEachLimit(apps, 1, (app, next) => {
var app_name
if (!app.name) {
Common.renderApplicationName(app)
}
if (apps.length > 1)
app_name = `${module_name}:${app.name}`
else if (apps.length == 1 && pkg.name != apps[0].name)
app_name = `${module_name}:${app.name}`
else
app_name = app.name
PM2._operate('deleteProcessId', app_name, () => {
deleteModulePath(module_name)
next()
})
}, () => {
Configuration.unsetSync(`${cst.MODULE_CONF_PREFIX_TAR}:${module_name}`)
cb(null)
})
}
/**
* Uncompress only module/package.json and retrieve the "name" attribute in the package.json
*/
function getModuleName(module_filepath, cb) {
var tmp_folder = path.join(os.tmpdir(), cst.MODULE_BASEFOLDER)
var install_instance = spawn('tar', ['zxf', module_filepath, '-C', os.tmpdir(), `${cst.MODULE_BASEFOLDER}/package.json`], {
stdio : 'inherit',
env: process.env,
shell : true
})
install_instance.on('close', function(code) {
try {
var pkg = JSON.parse(fs.readFileSync(path.join(tmp_folder, `package.json`)))
return cb(null, pkg.name)
} catch(e) {
return cb(e)
}
});
}
function packager(module_path, target_path, cb) {
var base_folder = path.dirname(module_path)
var module_folder_name = path.basename(module_path)
var pkg = require(path.join(module_path, 'package.json'))
var pkg_name = `${module_folder_name}-v${pkg.version.replace(/\./g, '-')}.tar.gz`
var target_fullpath = path.join(target_path, pkg_name)
var cmd = `tar zcf ${target_fullpath} -C ${base_folder} --transform 's,${module_folder_name},module,' ${module_folder_name}`
Common.logMod(`Gziping ${module_path} to ${target_fullpath}`)
var tar = exec(cmd, (err, sto, ste) => {
if (err) {
console.log(sto.toString().trim())
console.log(ste.toString().trim())
}
})
tar.on('close', function (code) {
cb(code == 0 ? null : code, {
package_name: pkg_name,
path: target_fullpath
})
})
}
function publish(PM2, folder, cb) {
var target_folder = folder ? path.resolve(folder) : process.cwd()
try {
var pkg = JSON.parse(fs.readFileSync(path.join(target_folder, 'package.json')).toString())
} catch(e) {
Common.errMod(`${process.cwd()} module does not contain any package.json`)
process.exit(1)
}
if (!pkg.name) throw new Error('Attribute name should be present')
if (!pkg.version) throw new Error('Attribute version should be present')
if (!pkg.pm2 && !pkg.apps) throw new Error('Attribute apps should be present')
var current_path = target_folder
var module_name = path.basename(current_path)
var target_path = os.tmpdir()
Common.logMod(`Starting publishing procedure for ${module_name}@${pkg.version}`)
packager(current_path, target_path, (err, res) => {
if (err) {
Common.errMod('Can\'t package, exiting')
process.exit(1)
}
Common.logMod(`Package [${pkg.name}] created in path ${res.path}`)
var data = {
module_data: {
file: res.path,
content_type: 'content/gzip'
},
id: pkg.name,
name: pkg.name,
version: pkg.version
};
var uri = `${PM2.pm2_configuration.registry}/api/v1/modules`
Common.logMod(`Sending Package to remote ${pkg.name} ${uri}`)
require('needle')
.post(uri, data, { multipart: true }, function(err, res, body) {
if (err) {
Common.errMod(err)
process.exit(1)
}
if (res.statusCode !== 200) {
Common.errMod(`${pkg.name}-${pkg.version}: ${res.body.msg}`)
process.exit(1)
}
Common.logMod(`Module ${module_name} published under version ${pkg.version}`)
process.exit(0)
})
})
}
function needPrefix(conf) {
if ((conf.apps && conf.apps.length > 1) ||
(conf.pm2 && conf.pm2.length > 1) ||
(conf.apps.length == 1 && conf.name != conf.apps[0].name))
return true
return false
}

View File

@@ -0,0 +1,46 @@
var fs = require('fs');
var conf = require('../../../constants.js');
function find_extensions(folder, ext, ret)
{
try {
fs.accessSync(folder, fs.constants.R_OK);
} catch (err) {
return;
}
if(fs.statSync(folder).isDirectory() && folder.indexOf('node_modules') == -1 && (fs.statSync(folder)["mode"] & 4))
{
fs.readdirSync(folder).forEach(file => {
var tmp;
if(Number.parseInt(folder.lastIndexOf('/') + 1) === folder.length)
tmp = folder + file;
else
tmp = folder + '/' + file;
if(fs.statSync(tmp).isDirectory())
find_extensions(tmp, ext, ret);
else
{
var p = true;
for(var i = 0; i < ext.length;i++)
if(ext[i].test(file))
p = false;
if(p)
ret.push(folder + '/' + file);
}
});
}
}
module.exports.make_available_extension = function make_available_extension(opts, ret)
{
if(typeof opts == 'object' && typeof ret == 'object')
{
var mas = opts.ext.split(',');
for(var i = 0;i < mas.length;i++)
mas[i] = '.' + mas[i];
var res = [];
for(var i = 0;i < mas.length;i++)
res[i] = new RegExp(mas[i] + '$');
find_extensions(process.cwd(), res, ret);
}
}

View File

@@ -0,0 +1,120 @@
/***************************
*
* Module methods
*
**************************/
var cst = require('../../../constants.js');
var Common = require('../../Common.js');
var chalk = require('chalk');
var forEachLimit = require('async/forEachLimit');
var Modularizer = require('./Modularizer.js');
module.exports = function(CLI) {
/**
* Install / Update a module
*/
CLI.prototype.install = function(module_name, opts, cb) {
var that = this;
if (typeof(opts) == 'function') {
cb = opts;
opts = {};
}
Modularizer.install(this, module_name, opts, function(err, data) {
if (err) {
Common.printError(cst.PREFIX_MSG_ERR + (err.message || err));
return cb ? cb(Common.retErr(err)) : that.speedList(cst.ERROR_EXIT);
}
return cb ? cb(null, data) : that.speedList(cst.SUCCESS_EXIT);
});
};
/**
* Uninstall a module
*/
CLI.prototype.uninstall = function(module_name, cb) {
var that = this;
Modularizer.uninstall(this, module_name, function(err, data) {
if (err)
return cb ? cb(Common.retErr(err)) : that.speedList(cst.ERROR_EXIT);
return cb ? cb(null, data) : that.speedList(cst.SUCCESS_EXIT);
});
};
CLI.prototype.launchAll = function(CLI, cb) {
Modularizer.launchModules(CLI, cb);
};
CLI.prototype.package = function(module_path, cb) {
Modularizer.package(this, module_path, (err, res) => {
if (err) {
Common.errMod(err)
return cb ? cb(err) : this.exitCli(1)
}
Common.logMod(`Module packaged in ${res.path}`)
return cb ? cb(err) : this.exitCli(0)
})
};
/**
* Publish module on NPM + Git push
*/
CLI.prototype.publish = function(folder, opts, cb) {
var that = this;
Modularizer.publish(this, folder, opts, function(err, data) {
if (err)
return cb ? cb(Common.retErr(err)) : that.speedList(cst.ERROR_EXIT);
return cb ? cb(null, data) : that.speedList(cst.SUCCESS_EXIT);
});
};
/**
* Publish module on NPM + Git push
*/
CLI.prototype.generateModuleSample = function(app_name, cb) {
var that = this;
Modularizer.generateSample(app_name, function(err, data) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
return cb ? cb(null, data) : that.exitCli(cst.SUCCESS_EXIT);
});
};
/**
* Special delete method
*/
CLI.prototype.deleteModule = function(module_name, cb) {
var that = this;
var found_proc = [];
this.Client.getAllProcess(function(err, procs) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(Common.retErr(err));
}
procs.forEach(function(proc) {
if (proc.pm2_env.name == module_name && proc.pm2_env.pmx_module) {
found_proc.push(proc.pm_id);
}
});
if (found_proc.length == 0)
return cb();
that._operate('deleteProcessId', found_proc[0], function(err) {
if (err) return cb(Common.retErr(err));
Common.printOut('In memory process deleted');
return cb();
});
});
};
};

247
api.hyungi.net/node_modules/pm2/lib/API/Monit.js generated vendored Normal file
View File

@@ -0,0 +1,247 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
// pm2-htop
// Library who interacts with PM2 to display processes resources in htop way
// by Strzelewicz Alexandre
var multimeter = require('pm2-multimeter');
var os = require('os');
var p = require('path');
var chalk = require('chalk');
var UX = require('./UX');
var debug = require('debug')('pm2:monit');
// Cst for light programs
const RATIO_T1 = Math.floor(os.totalmem() / 500);
// Cst for medium programs
const RATIO_T2 = Math.floor(os.totalmem() / 50);
// Cst for heavy programs
const RATIO_T3 = Math.floor(os.totalmem() / 5);
// Cst for heavy programs
const RATIO_T4 = Math.floor(os.totalmem());
var Monit = {};
//helper to get bars.length (num bars printed)
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
/**
* Reset the monitor through charm, basically \033c
* @param String msg optional message to show
* @return Monit
*/
Monit.reset = function(msg) {
this.multi.charm.reset();
this.multi.write('\x1B[32m⌬ PM2 \x1B[39mmonitoring\x1B[96m (To go further check out https://app.pm2.io) \x1B[39m\n\n');
if(msg) {
this.multi.write(msg);
}
this.bars = {};
return this;
}
/**
* Synchronous Monitor init method
* @method init
* @return Monit
*/
Monit.init = function() {
this.multi = multimeter(process);
this.multi.on('^C', this.stop);
this.reset();
return this;
}
/**
* Stops monitor
* @method stop
*/
Monit.stop = function() {
this.multi.charm.destroy();
process.exit(0);
}
/**
* Refresh monitor
* @method refresh
* @param {} processes
* @return this
*/
Monit.refresh = function(processes) {
debug('Monit refresh');
if(!processes) {
processes = [];
}
var num = processes.length;
this.num_bars = Object.size(this.bars);
if(num !== this.num_bars) {
debug('Monit addProcesses - actual: %s, new: %s', this.num_bars, num);
return this.addProcesses(processes);
} else {
if(num === 0) {
return;
}
debug('Monit refresh');
var proc;
for(var i = 0; i < num; i++) {
proc = processes[i];
//this is to avoid a print issue when the process is restarted for example
//we might also check for the pid but restarted|restarting will be rendered bad
if(this.bars[proc.pm_id] && proc.pm2_env.status !== this.bars[proc.pm_id].status) {
debug('bars for %s does not exist', proc.pm_id);
this.addProcesses(processes);
break;
}
this.updateBars(proc);
}
}
return this;
}
Monit.addProcess = function(proc, i) {
if(proc.pm_id in this.bars) {
return ;
}
if (proc.monit.error)
throw new Error(JSON.stringify(proc.monit.error));
var process_name = proc.pm2_env.name || p.basename(proc.pm2_env.pm_exec_path);
var status = proc.pm2_env.status == 'online' ? chalk.green.bold('●') : chalk.red.bold('●');
this.multi.write(' ' + status + ' ' + chalk.green.bold(process_name));
this.multi.write('\n');
this.multi.write('[' + proc.pm2_env.pm_id + '] [' + proc.pm2_env.exec_mode + ']\n');
var bar_cpu = this.multi(40, (i * 2) + 3 + i, {
width: 30,
solid: {
text: '|',
foreground: 'white',
background: 'blue'
},
empty: {
text: ' '
}
});
var bar_memory = this.multi(40, (i * 2) + 4 + i, {
width: 30,
solid: {
text: '|',
foreground: 'white',
background: 'red'
},
empty: {
text: ' '
}
});
this.bars[proc.pm_id] = {
memory: bar_memory,
cpu: bar_cpu,
status: proc.pm2_env.status
};
this.updateBars(proc);
this.multi.write('\n');
return this;
}
Monit.addProcesses = function(processes) {
if(!processes) {
processes = [];
}
this.reset();
var num = processes.length;
if(num > 0) {
for(var i = 0; i < num; i++) {
this.addProcess(processes[i], i);
}
} else {
this.reset('No processes to monit');
}
}
// Draw memory bars
/**
* Description
* @method drawRatio
* @param {} bar_memory
* @param {} memory
* @return
*/
Monit.drawRatio = function(bar_memory, memory) {
var scale = 0;
if (memory < RATIO_T1) scale = RATIO_T1;
else if (memory < RATIO_T2) scale = RATIO_T2;
else if (memory < RATIO_T3) scale = RATIO_T3;
else scale = RATIO_T4;
bar_memory.ratio(memory,
scale,
UX.helpers.bytesToSize(memory, 3));
};
/**
* Updates bars informations
* @param {} proc proc object
* @return this
*/
Monit.updateBars = function(proc) {
if (this.bars[proc.pm_id]) {
if (proc.pm2_env.status !== 'online' || proc.pm2_env.status !== this.bars[proc.pm_id].status) {
this.bars[proc.pm_id].cpu.percent(0, chalk.red(proc.pm2_env.status));
this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red(proc.pm2_env.status));
} else if (!proc.monit) {
this.bars[proc.pm_id].cpu.percent(0, chalk.red('No data'));
this.drawRatio(this.bars[proc.pm_id].memory, 0, chalk.red('No data'));
} else {
this.bars[proc.pm_id].cpu.percent(proc.monit.cpu);
this.drawRatio(this.bars[proc.pm_id].memory, proc.monit.memory);
}
}
return this;
}
module.exports = Monit;

342
api.hyungi.net/node_modules/pm2/lib/API/Serve.js generated vendored Normal file
View File

@@ -0,0 +1,342 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
var fs = require('fs');
var http = require('http');
var url = require('url');
var path = require('path');
var debug = require('debug')('pm2:serve');
var probe = require('@pm2/io');
var errorMeter = probe.meter({
name : '404/sec',
samples : 1,
timeframe : 60
})
/**
* list of supported content types.
*/
var contentTypes = {
'3gp': 'video/3gpp',
'a': 'application/octet-stream',
'ai': 'application/postscript',
'aif': 'audio/x-aiff',
'aiff': 'audio/x-aiff',
'asc': 'application/pgp-signature',
'asf': 'video/x-ms-asf',
'asm': 'text/x-asm',
'asx': 'video/x-ms-asf',
'atom': 'application/atom+xml',
'au': 'audio/basic',
'avi': 'video/x-msvideo',
'bat': 'application/x-msdownload',
'bin': 'application/octet-stream',
'bmp': 'image/bmp',
'bz2': 'application/x-bzip2',
'c': 'text/x-c',
'cab': 'application/vnd.ms-cab-compressed',
'cc': 'text/x-c',
'chm': 'application/vnd.ms-htmlhelp',
'class': 'application/octet-stream',
'com': 'application/x-msdownload',
'conf': 'text/plain',
'cpp': 'text/x-c',
'crt': 'application/x-x509-ca-cert',
'css': 'text/css',
'csv': 'text/csv',
'cxx': 'text/x-c',
'deb': 'application/x-debian-package',
'der': 'application/x-x509-ca-cert',
'diff': 'text/x-diff',
'djv': 'image/vnd.djvu',
'djvu': 'image/vnd.djvu',
'dll': 'application/x-msdownload',
'dmg': 'application/octet-stream',
'doc': 'application/msword',
'dot': 'application/msword',
'dtd': 'application/xml-dtd',
'dvi': 'application/x-dvi',
'ear': 'application/java-archive',
'eml': 'message/rfc822',
'eps': 'application/postscript',
'exe': 'application/x-msdownload',
'f': 'text/x-fortran',
'f77': 'text/x-fortran',
'f90': 'text/x-fortran',
'flv': 'video/x-flv',
'for': 'text/x-fortran',
'gem': 'application/octet-stream',
'gemspec': 'text/x-script.ruby',
'gif': 'image/gif',
'gz': 'application/x-gzip',
'h': 'text/x-c',
'hh': 'text/x-c',
'htm': 'text/html',
'html': 'text/html',
'ico': 'image/vnd.microsoft.icon',
'ics': 'text/calendar',
'ifb': 'text/calendar',
'iso': 'application/octet-stream',
'jar': 'application/java-archive',
'java': 'text/x-java-source',
'jnlp': 'application/x-java-jnlp-file',
'jpeg': 'image/jpeg',
'jpg': 'image/jpeg',
'js': 'application/javascript',
'json': 'application/json',
'log': 'text/plain',
'm3u': 'audio/x-mpegurl',
'm4v': 'video/mp4',
'man': 'text/troff',
'mathml': 'application/mathml+xml',
'mbox': 'application/mbox',
'mdoc': 'text/troff',
'me': 'text/troff',
'mid': 'audio/midi',
'midi': 'audio/midi',
'mime': 'message/rfc822',
'mml': 'application/mathml+xml',
'mng': 'video/x-mng',
'mov': 'video/quicktime',
'mp3': 'audio/mpeg',
'mp4': 'video/mp4',
'mp4v': 'video/mp4',
'mpeg': 'video/mpeg',
'mpg': 'video/mpeg',
'ms': 'text/troff',
'msi': 'application/x-msdownload',
'odp': 'application/vnd.oasis.opendocument.presentation',
'ods': 'application/vnd.oasis.opendocument.spreadsheet',
'odt': 'application/vnd.oasis.opendocument.text',
'ogg': 'application/ogg',
'p': 'text/x-pascal',
'pas': 'text/x-pascal',
'pbm': 'image/x-portable-bitmap',
'pdf': 'application/pdf',
'pem': 'application/x-x509-ca-cert',
'pgm': 'image/x-portable-graymap',
'pgp': 'application/pgp-encrypted',
'pkg': 'application/octet-stream',
'pl': 'text/x-script.perl',
'pm': 'text/x-script.perl-module',
'png': 'image/png',
'pnm': 'image/x-portable-anymap',
'ppm': 'image/x-portable-pixmap',
'pps': 'application/vnd.ms-powerpoint',
'ppt': 'application/vnd.ms-powerpoint',
'ps': 'application/postscript',
'psd': 'image/vnd.adobe.photoshop',
'py': 'text/x-script.python',
'qt': 'video/quicktime',
'ra': 'audio/x-pn-realaudio',
'rake': 'text/x-script.ruby',
'ram': 'audio/x-pn-realaudio',
'rar': 'application/x-rar-compressed',
'rb': 'text/x-script.ruby',
'rdf': 'application/rdf+xml',
'roff': 'text/troff',
'rpm': 'application/x-redhat-package-manager',
'rss': 'application/rss+xml',
'rtf': 'application/rtf',
'ru': 'text/x-script.ruby',
's': 'text/x-asm',
'sgm': 'text/sgml',
'sgml': 'text/sgml',
'sh': 'application/x-sh',
'sig': 'application/pgp-signature',
'snd': 'audio/basic',
'so': 'application/octet-stream',
'svg': 'image/svg+xml',
'svgz': 'image/svg+xml',
'swf': 'application/x-shockwave-flash',
't': 'text/troff',
'tar': 'application/x-tar',
'tbz': 'application/x-bzip-compressed-tar',
'tcl': 'application/x-tcl',
'tex': 'application/x-tex',
'texi': 'application/x-texinfo',
'texinfo': 'application/x-texinfo',
'text': 'text/plain',
'tif': 'image/tiff',
'tiff': 'image/tiff',
'torrent': 'application/x-bittorrent',
'tr': 'text/troff',
'txt': 'text/plain',
'vcf': 'text/x-vcard',
'vcs': 'text/x-vcalendar',
'vrml': 'model/vrml',
'war': 'application/java-archive',
'wav': 'audio/x-wav',
'wma': 'audio/x-ms-wma',
'wmv': 'video/x-ms-wmv',
'wmx': 'video/x-ms-wmx',
'wrl': 'model/vrml',
'wsdl': 'application/wsdl+xml',
'xbm': 'image/x-xbitmap',
'xhtml': 'application/xhtml+xml',
'xls': 'application/vnd.ms-excel',
'xml': 'application/xml',
'xpm': 'image/x-xpixmap',
'xsl': 'application/xml',
'xslt': 'application/xslt+xml',
'yaml': 'text/yaml',
'yml': 'text/yaml',
'zip': 'application/zip',
'woff': 'application/font-woff',
'woff2': 'application/font-woff',
'otf': 'application/font-sfnt',
'otc': 'application/font-sfnt',
'ttf': 'application/font-sfnt'
};
var options = {
port: process.env.PM2_SERVE_PORT || process.argv[3] || 8080,
host: process.env.PM2_SERVE_HOST || process.argv[4] || '0.0.0.0',
path: path.resolve(process.env.PM2_SERVE_PATH || process.argv[2] || '.'),
spa: process.env.PM2_SERVE_SPA === 'true',
homepage: process.env.PM2_SERVE_HOMEPAGE || '/index.html',
basic_auth: process.env.PM2_SERVE_BASIC_AUTH === 'true' ? {
username: process.env.PM2_SERVE_BASIC_AUTH_USERNAME,
password: process.env.PM2_SERVE_BASIC_AUTH_PASSWORD
} : null,
monitor: process.env.PM2_SERVE_MONITOR
};
if (typeof options.port === 'string') {
options.port = parseInt(options.port) || 8080
}
if (typeof options.monitor === 'string' && options.monitor !== '') {
try {
let fileContent = fs.readFileSync(path.join(process.env.PM2_HOME, 'agent.json5')).toString()
// Handle old configuration with json5
fileContent = fileContent.replace(/\s(\w+):/g, '"$1":')
// parse
let conf = JSON.parse(fileContent)
options.monitorBucket = conf.public_key
} catch (e) {
console.log('Interaction file does not exist')
}
}
// start an HTTP server
http.createServer(function (request, response) {
if (options.basic_auth) {
if (!request.headers.authorization || request.headers.authorization.indexOf('Basic ') === -1) {
return sendBasicAuthResponse(response)
}
var user = parseBasicAuth(request.headers.authorization)
if (user.username !== options.basic_auth.username || user.password !== options.basic_auth.password) {
return sendBasicAuthResponse(response)
}
}
serveFile(request.url, request, response);
}).listen(options.port, options.host, function (err) {
if (err) {
console.error(err);
process.exit(1);
}
console.log('Exposing %s directory on %s:%d', options.path, options.host, options.port);
});
function serveFile(uri, request, response) {
var file = decodeURIComponent(url.parse(uri || request.url).pathname);
if (file === '/' || file === '') {
file = options.homepage;
request.wantHomepage = true;
}
var filePath = path.resolve(options.path + file);
// since we call filesystem directly so we need to verify that the
// url doesn't go outside the serve path
if (filePath.indexOf(options.path) !== 0) {
response.writeHead(403, { 'Content-Type': 'text/html' });
return response.end('403 Forbidden');
}
var contentType = contentTypes[filePath.split('.').pop().toLowerCase()] || 'text/plain';
fs.readFile(filePath, function (error, content) {
if (error) {
if ((!options.spa || file === options.homepage)) {
console.error('[%s] Error while serving %s with content-type %s : %s',
new Date(), filePath, contentType, error.message || error);
}
errorMeter.mark();
if (error.code === 'ENOENT') {
if (options.spa && !request.wantHomepage) {
request.wantHomepage = true;
return serveFile(`/${path.basename(file)}`, request, response);
} else if (options.spa && file !== options.homepage) {
return serveFile(options.homepage, request, response);
}
fs.readFile(options.path + '/404.html', function (err, content) {
content = err ? '404 Not Found' : content;
response.writeHead(404, { 'Content-Type': 'text/html' });
return response.end(content, 'utf-8');
});
return;
}
response.writeHead(500);
return response.end('Sorry, check with the site admin for error: ' + error.code + ' ..\n');
}
// Add CORS headers to allow browsers to fetch data directly
response.writeHead(200, {
'Content-Type': contentType,
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET'
});
if (options.monitorBucket && contentType === 'text/html') {
content = content.toString().replace('</body>', `
<script>
;(function (b,e,n,o,i,t) {
b[o]=b[o]||function(f){(b[o].c=b[o].c||[]).push(f)};
t=e.createElement(i);e=e.getElementsByTagName(i)[0];
t.async=1;t.src=n;e.parentNode.insertBefore(t,e);
}(window,document,'https://apm.pm2.io/pm2-io-apm-browser.v1.js','pm2Ready','script'))
pm2Ready(function(apm) {
apm.setBucket('${options.monitorBucket}')
apm.setApplication('${options.monitor}')
apm.reportTimings()
apm.reportIssues()
})
</script>
</body>
`);
}
response.end(content, 'utf-8');
debug('[%s] Serving %s with content-type %s', Date.now(), filePath, contentType);
});
}
function parseBasicAuth(auth) {
// auth is like `Basic Y2hhcmxlczoxMjM0NQ==`
var tmp = auth.split(' ');
var buf = Buffer.from(tmp[1], 'base64');
var plain = buf.toString();
var creds = plain.split(':');
return {
username: creds[0],
password: creds[1]
}
}
function sendBasicAuthResponse(response) {
response.writeHead(401, {
'Content-Type': 'text/html',
'WWW-Authenticate': 'Basic realm="Authentication service"'
});
return response.end('401 Unauthorized');
}

616
api.hyungi.net/node_modules/pm2/lib/API/Startup.js generated vendored Normal file
View File

@@ -0,0 +1,616 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var chalk = require('chalk');
var path = require('path');
var fs = require('fs');
var forEachLimit = require('async/forEachLimit');
var eachLimit = require('async/eachLimit');
var Common = require('../Common.js');
var cst = require('../../constants.js');
var util = require('util');
var tmpPath = require('os').tmpdir;
var which = require('../tools/which.js');
var sexec = require('../tools/sexec')
module.exports = function(CLI) {
/**
* If command is launched without root right
* Display helper
*/
function isNotRoot(startup_mode, platform, opts, cb) {
Common.printOut(`${cst.PREFIX_MSG}To ${startup_mode} the Startup Script, copy/paste the following command:`);
if (opts.user) {
console.log('sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' pm2 ' + opts.args[1].name() + ' ' + platform + ' -u ' + opts.user + ' --hp ' + process.env.HOME);
return cb(new Error('You have to run this with elevated rights'));
}
return sexec('whoami', {silent: true}, function(err, stdout, stderr) {
console.log('sudo env PATH=$PATH:' + path.dirname(process.execPath) + ' ' + require.main.filename + ' ' + opts.args[1].name() + ' ' + platform + ' -u ' + stdout.trim() + ' --hp ' + process.env.HOME);
return cb(new Error('You have to run this with elevated rights'));
});
}
/**
* Detect running init system
*/
function detectInitSystem() {
var hash_map = {
'systemctl' : 'systemd',
'update-rc.d': 'upstart',
'chkconfig' : 'systemv',
'rc-update' : 'openrc',
'launchctl' : 'launchd',
'sysrc' : 'rcd',
'rcctl' : 'rcd-openbsd',
'svcadm' : 'smf'
};
var init_systems = Object.keys(hash_map);
for (var i = 0; i < init_systems.length; i++) {
if (which(init_systems[i]) != null) {
break;
}
}
if (i >= init_systems.length) {
Common.printError(cst.PREFIX_MSG_ERR + 'Init system not found');
return null;
}
Common.printOut(cst.PREFIX_MSG + 'Init System found: ' + chalk.bold(hash_map[init_systems[i]]));
return hash_map[init_systems[i]];
}
CLI.prototype.uninstallStartup = function(platform, opts, cb) {
var commands;
var that = this;
var actual_platform = detectInitSystem();
var user = opts.user || process.env.USER || process.env.LOGNAME; // Use LOGNAME on Solaris-like systems
var service_name = (opts.serviceName || 'pm2-' + user);
var openrc_service_name = 'pm2';
var launchd_service_name = (opts.serviceName || 'pm2.' + user);
if (!platform)
platform = actual_platform;
else if (actual_platform && actual_platform !== platform) {
Common.printOut('-----------------------------------------------------------')
Common.printOut(' PM2 detected ' + actual_platform + ' but you precised ' + platform)
Common.printOut(' Please verify that your choice is indeed your init system')
Common.printOut(' If you arent sure, just run : pm2 startup')
Common.printOut('-----------------------------------------------------------')
}
if (platform === null)
throw new Error('Init system not found')
if (!cb) {
cb = function(err, data) {
if (err)
return that.exitCli(cst.ERROR_EXIT);
return that.exitCli(cst.SUCCESS_EXIT);
}
}
if (process.getuid() != 0) {
return isNotRoot('unsetup', platform, opts, cb);
}
if (fs.existsSync('/etc/init.d/pm2-init.sh')) {
platform = 'oldsystem';
}
switch(platform) {
case 'systemd':
commands = [
'systemctl stop ' + service_name,
'systemctl disable ' + service_name,
'rm /etc/systemd/system/' + service_name + '.service'
];
break;
case 'systemv':
commands = [
'chkconfig ' + service_name + ' off',
'rm /etc/init.d/' + service_name
];
break;
case 'oldsystem':
Common.printOut(cst.PREFIX_MSG + 'Disabling and deleting old startup system');
commands = [
'update-rc.d pm2-init.sh disable',
'update-rc.d -f pm2-init.sh remove',
'rm /etc/init.d/pm2-init.sh'
];
break;
case 'openrc':
service_name = openrc_service_name;
commands = [
'/etc/init.d/' + service_name + ' stop',
'rc-update delete ' + service_name + ' default',
'rm /etc/init.d/' + service_name
];
break;
case 'upstart':
commands = [
'update-rc.d ' + service_name + ' disable',
'update-rc.d -f ' + service_name + ' remove',
'rm /etc/init.d/' + service_name
];
break;
case 'launchd':
var destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist');
commands = [
'launchctl remove ' + launchd_service_name + ' || true',
'rm ' + destination
];
break;
case 'rcd':
service_name = (opts.serviceName || 'pm2_' + user);
commands = [
'/usr/local/etc/rc.d/' + service_name + ' stop',
'sysrc -x ' + service_name + '_enable',
'rm /usr/local/etc/rc.d/' + service_name
];
break;
case 'rcd-openbsd':
service_name = (opts.serviceName || 'pm2_' + user);
var destination = path.join('/etc/rc.d', service_name);
commands = [
'rcctl stop ' + service_name,
'rcctl disable ' + service_name,
'rm ' + destination
];
break;
case 'smf':
service_name = (opts.serviceName || 'pm2_' + user);
commands = [
'svcadm disable ' + service_name,
'svccfg delete -f ' + service_name
]
};
sexec(commands.join('&& '), function(code, stdout, stderr) {
Common.printOut(stdout);
Common.printOut(stderr);
if (code == 0) {
Common.printOut(cst.PREFIX_MSG + chalk.bold('Init file disabled.'));
} else {
Common.printOut(cst.ERROR_MSG + chalk.bold('Return code : ' + code));
}
cb(null, {
commands : commands,
platform : platform
});
});
};
/**
* Startup script generation
* @method startup
* @param {string} platform type (centos|redhat|amazon|gentoo|systemd|smf)
*/
CLI.prototype.startup = function(platform, opts, cb) {
var that = this;
var actual_platform = detectInitSystem();
var user = (opts.user || process.env.USER || process.env.LOGNAME); // Use LOGNAME on Solaris-like systems
var service_name = (opts.serviceName || 'pm2-' + user);
var openrc_service_name = 'pm2';
var launchd_service_name = (opts.serviceName || 'pm2.' + user);
if (!platform)
platform = actual_platform;
else if (actual_platform && actual_platform !== platform) {
Common.printOut('-----------------------------------------------------------')
Common.printOut(' PM2 detected ' + actual_platform + ' but you precised ' + platform)
Common.printOut(' Please verify that your choice is indeed your init system')
Common.printOut(' If you arent sure, just run : pm2 startup')
Common.printOut('-----------------------------------------------------------')
}
if (platform == null)
throw new Error('Init system not found');
if (!cb) {
cb = function(err, data) {
if (err)
return that.exitCli(cst.ERROR_EXIT);
return that.exitCli(cst.SUCCESS_EXIT);
}
}
if (process.getuid() != 0) {
return isNotRoot('setup', platform, opts, cb);
}
var destination;
var commands;
var template;
function getTemplate(type) {
return fs.readFileSync(path.join(__dirname, '..', 'templates/init-scripts', type + '.tpl'), {encoding: 'utf8'});
}
switch(platform) {
case 'ubuntu':
case 'centos':
case 'arch':
case 'oracle':
case 'systemd':
if (opts.waitIp)
template = getTemplate('systemd-online');
else
template = getTemplate('systemd');
destination = '/etc/systemd/system/' + service_name + '.service';
commands = [
'systemctl enable ' + service_name
];
break;
case 'ubuntu14':
case 'ubuntu12':
case 'upstart':
template = getTemplate('upstart');
destination = '/etc/init.d/' + service_name;
commands = [
'chmod +x ' + destination,
'mkdir -p /var/lock/subsys',
'touch /var/lock/subsys/' + service_name,
'update-rc.d ' + service_name + ' defaults'
];
break;
case 'systemv':
case 'amazon':
case 'centos6':
template = getTemplate('upstart');
destination = '/etc/init.d/' + service_name;
commands = [
'chmod +x ' + destination,
'mkdir -p /var/lock/subsys',
'touch /var/lock/subsys/' + service_name,
'chkconfig --add ' + service_name,
'chkconfig ' + service_name + ' on',
'initctl list'
];
break;
case 'macos':
case 'darwin':
case 'launchd':
template = getTemplate('launchd');
destination = path.join(process.env.HOME, 'Library/LaunchAgents/' + launchd_service_name + '.plist');
commands = [
'mkdir -p ' + path.join(process.env.HOME, 'Library/LaunchAgents'),
'launchctl load -w ' + destination
]
break;
case 'freebsd':
case 'rcd':
template = getTemplate('rcd');
service_name = (opts.serviceName || 'pm2_' + user);
destination = '/usr/local/etc/rc.d/' + service_name;
commands = [
'chmod 755 ' + destination,
'sysrc ' + service_name + '_enable=YES'
];
break;
case 'openbsd':
case 'rcd-openbsd':
template = getTemplate('rcd-openbsd');
service_name = (opts.serviceName || 'pm2_' + user);
destination = path.join('/etc/rc.d/', service_name);
commands = [
'chmod 755 ' + destination,
'rcctl enable ' + service_name,
'rcctl start ' + service_name
];
break;
case 'openrc':
template = getTemplate('openrc');
service_name = openrc_service_name;
destination = '/etc/init.d/' + service_name;
commands = [
'chmod +x ' + destination,
'rc-update add ' + service_name + ' default'
];
break;
case 'smf':
case 'sunos':
case 'solaris':
template = getTemplate('smf');
service_name = (opts.serviceName || 'pm2_' + user);
destination = path.join(tmpPath(), service_name + '.xml');
commands = [
'svccfg import ' + destination,
'svcadm enable ' + service_name
];
break;
default:
throw new Error('Unknown platform / init system name');
}
/**
* 4# Replace template variable value
*/
var envPath
if (cst.HAS_NODE_EMBEDDED == true)
envPath = util.format('%s:%s', process.env.PATH || '', path.dirname(process.execPath))
else if (new RegExp(path.dirname(process.execPath)).test(process.env.PATH))
envPath = process.env.PATH
else
envPath = util.format('%s:%s', process.env.PATH || '', path.dirname(process.execPath))
template = template.replace(/%PM2_PATH%/g, process.mainModule.filename)
.replace(/%NODE_PATH%/g, envPath)
.replace(/%USER%/g, user)
.replace(/%HOME_PATH%/g, opts.hp ? path.resolve(opts.hp, '.pm2') : cst.PM2_ROOT_PATH)
.replace(/%SERVICE_NAME%/g, service_name);
Common.printOut(chalk.bold('Platform'), platform);
Common.printOut(chalk.bold('Template'));
Common.printOut(template);
Common.printOut(chalk.bold('Target path'));
Common.printOut(destination);
Common.printOut(chalk.bold('Command list'));
Common.printOut(commands);
Common.printOut(cst.PREFIX_MSG + 'Writing init configuration in ' + destination);
try {
fs.writeFileSync(destination, template);
} catch (e) {
console.error(cst.PREFIX_MSG_ERR + 'Failure when trying to write startup script');
console.error(e.message || e);
return cb(e);
}
Common.printOut(cst.PREFIX_MSG + 'Making script booting at startup...');
forEachLimit(commands, 1, function(command, next) {
Common.printOut(cst.PREFIX_MSG + '[-] Executing: %s...', chalk.bold(command));
sexec(command, function(code, stdout, stderr) {
if (code === 0) {
Common.printOut(cst.PREFIX_MSG + chalk.bold('[v] Command successfully executed.'));
return next();
} else {
Common.printOut(chalk.red('[ERROR] Exit code : ' + code))
return next(new Error(command + ' failed, see error above.'));
}
})
}, function(err) {
if (err) {
console.error(cst.PREFIX_MSG_ERR + (err.message || err));
return cb(err);
}
Common.printOut(chalk.bold.blue('+---------------------------------------+'));
Common.printOut(chalk.bold.blue((cst.PREFIX_MSG + 'Freeze a process list on reboot via:' )));
Common.printOut(chalk.bold('$ pm2 save'));
Common.printOut('');
Common.printOut(chalk.bold.blue(cst.PREFIX_MSG + 'Remove init script via:'));
Common.printOut(chalk.bold('$ pm2 unstartup ' + platform));
return cb(null, {
destination : destination,
template : template
});
});
};
/**
* DISABLED FEATURE
* KEEPING METHOD FOR BACKWARD COMPAT
*/
CLI.prototype.autodump = function(cb) {
return cb()
}
/**
* Dump current processes managed by pm2 into DUMP_FILE_PATH file
* @method dump
* @param {} cb
* @return
*/
CLI.prototype.dump = function(force, cb) {
var env_arr = [];
var that = this;
if (typeof(force) === 'function') {
cb = force
force = false
}
if (!cb)
Common.printOut(cst.PREFIX_MSG + 'Saving current process list...');
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
/**
* Description
* @method fin
* @param {} err
* @return
*/
function fin(err) {
// try to fix issues with empty dump file
// like #3485
if (!force && env_arr.length === 0 && !process.env.FORCE) {
// fix : if no dump file, no process, only module and after pm2 update
if (!fs.existsSync(cst.DUMP_FILE_PATH)) {
that.clearDump(function(){});
}
// if no process in list don't modify dump file
// process list should not be empty
if (cb) {
return cb(new Error('Process list empty, cannot save empty list'));
} else {
Common.printOut(cst.PREFIX_MSG_WARNING + 'PM2 is not managing any process, skipping save...');
Common.printOut(cst.PREFIX_MSG_WARNING + 'To force saving use: pm2 save --force');
that.exitCli(cst.SUCCESS_EXIT);
return;
}
}
// Back up dump file
try {
if (fs.existsSync(cst.DUMP_FILE_PATH)) {
fs.writeFileSync(cst.DUMP_BACKUP_FILE_PATH, fs.readFileSync(cst.DUMP_FILE_PATH));
}
} catch (e) {
console.error(e.stack || e);
Common.printOut(cst.PREFIX_MSG_ERR + 'Failed to back up dump file in %s', cst.DUMP_BACKUP_FILE_PATH);
}
// Overwrite dump file, delete if broken and exit
try {
fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify(env_arr, '', 2));
} catch (e) {
console.error(e.stack || e);
try {
// try to backup file
if (fs.existsSync(cst.DUMP_BACKUP_FILE_PATH)) {
fs.writeFileSync(cst.DUMP_FILE_PATH, fs.readFileSync(cst.DUMP_BACKUP_FILE_PATH));
}
} catch (e) {
// don't keep broken file
fs.unlinkSync(cst.DUMP_FILE_PATH);
console.error(e.stack || e);
}
Common.printOut(cst.PREFIX_MSG_ERR + 'Failed to save dump file in %s', cst.DUMP_FILE_PATH);
return that.exitCli(cst.ERROR_EXIT);
}
if (cb) return cb(null, {success:true});
Common.printOut(cst.PREFIX_MSG + 'Successfully saved in %s', cst.DUMP_FILE_PATH);
return that.exitCli(cst.SUCCESS_EXIT);
}
(function ex(apps) {
if (!apps[0]) return fin(null);
delete apps[0].pm2_env.instances;
delete apps[0].pm2_env.pm_id;
delete apps[0].pm2_env.prev_restart_delay;
if (!apps[0].pm2_env.pmx_module)
env_arr.push(apps[0].pm2_env);
apps.shift();
return ex(apps);
})(list);
});
};
/**
* Remove DUMP_FILE_PATH file and DUMP_BACKUP_FILE_PATH file
* @method dump
* @param {} cb
* @return
*/
CLI.prototype.clearDump = function(cb) {
fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify([]));
if(cb && typeof cb === 'function') return cb();
Common.printOut(cst.PREFIX_MSG + 'Successfully created %s', cst.DUMP_FILE_PATH);
return this.exitCli(cst.SUCCESS_EXIT);
};
/**
* Resurrect processes
* @method resurrect
* @param {} cb
* @return
*/
CLI.prototype.resurrect = function(cb) {
var apps = {};
var that = this;
var processes;
function readDumpFile(dumpFilePath) {
Common.printOut(cst.PREFIX_MSG + 'Restoring processes located in %s', dumpFilePath);
try {
var apps = fs.readFileSync(dumpFilePath);
} catch (e) {
Common.printError(cst.PREFIX_MSG_ERR + 'Failed to read dump file in %s', dumpFilePath);
throw e;
}
return apps;
}
function parseDumpFile(dumpFilePath, apps) {
try {
var processes = Common.parseConfig(apps, 'none');
} catch (e) {
Common.printError(cst.PREFIX_MSG_ERR + 'Failed to parse dump file in %s', dumpFilePath);
try {
fs.unlinkSync(dumpFilePath);
} catch (e) {
console.error(e.stack || e);
}
throw e;
}
return processes;
}
// Read dump file, fall back to backup, delete if broken
try {
apps = readDumpFile(cst.DUMP_FILE_PATH);
processes = parseDumpFile(cst.DUMP_FILE_PATH, apps);
} catch(e) {
try {
apps = readDumpFile(cst.DUMP_BACKUP_FILE_PATH);
processes = parseDumpFile(cst.DUMP_BACKUP_FILE_PATH, apps);
} catch(e) {
Common.printError(cst.PREFIX_MSG_ERR + 'No processes saved; DUMP file doesn\'t exist');
// if (cb) return cb(Common.retErr(e));
// else return that.exitCli(cst.ERROR_EXIT);
return that.speedList();
}
}
that.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError(err);
return that.exitCli(1);
}
var current = [];
var target = [];
list.forEach(function(app) {
if (!current[app.name])
current[app.name] = 0;
current[app.name]++;
});
processes.forEach(function(app) {
if (!target[app.name])
target[app.name] = 0;
target[app.name]++;
});
var tostart = Object.keys(target).filter(function(i) {
return Object.keys(current).indexOf(i) < 0;
})
eachLimit(processes, cst.CONCURRENT_ACTIONS, function(app, next) {
if (tostart.indexOf(app.name) == -1)
return next();
that.Client.executeRemote('prepare', app, function(err, dt) {
if (err)
Common.printError(err);
else
Common.printOut(cst.PREFIX_MSG + 'Process %s restored', app.pm_exec_path);
next();
});
}, function(err) {
return cb ? cb(null, apps) : that.speedList();
});
});
};
}

213
api.hyungi.net/node_modules/pm2/lib/API/UX/helpers.js generated vendored Normal file
View File

@@ -0,0 +1,213 @@
const chalk = require('chalk')
const Helpers = {}
/**
* Converts Byte to Human readable size
* @method bytesToSize
* @param {} bytes
* @param {} precision
* @return
*/
Helpers.bytesToSize = function(bytes, precision) {
var kilobyte = 1024
var megabyte = kilobyte * 1024
var gigabyte = megabyte * 1024
var terabyte = gigabyte * 1024
if ((bytes >= 0) && (bytes < kilobyte)) {
return bytes + 'b '
} else if ((bytes >= kilobyte) && (bytes < megabyte)) {
return (bytes / kilobyte).toFixed(precision) + 'kb '
} else if ((bytes >= megabyte) && (bytes < gigabyte)) {
return (bytes / megabyte).toFixed(precision) + 'mb '
} else if ((bytes >= gigabyte) && (bytes < terabyte)) {
return (bytes / gigabyte).toFixed(precision) + 'gb '
} else if (bytes >= terabyte) {
return (bytes / terabyte).toFixed(precision) + 'tb '
} else {
return bytes + 'b '
}
}
/**
* Color Process state
* @method colorStatus
* @param {} status
* @return
*/
Helpers.colorStatus = function(status) {
switch (status) {
case 'online':
return chalk.green.bold('online')
break
case 'running':
return chalk.green.bold('online')
break
case 'restarting':
return chalk.yellow.bold('restart')
break
case 'created':
return chalk.yellow.bold('created')
break
case 'launching':
return chalk.blue.bold('launching')
break
default:
return chalk.red.bold(status)
}
}
/**
* Safe Push
*/
Helpers.safe_push = function() {
var argv = arguments
var table = argv[0]
for (var i = 1; i < argv.length; ++i) {
var elem = argv[i]
if (elem[Object.keys(elem)[0]] === undefined
|| elem[Object.keys(elem)[0]] === null) {
elem[Object.keys(elem)[0]] = 'N/A'
}
else if (Array.isArray(elem[Object.keys(elem)[0]])) {
elem[Object.keys(elem)[0]].forEach(function(curr, j) {
if (curr === undefined || curr === null)
elem[Object.keys(elem)[0]][j] = 'N/A'
})
}
table.push(elem)
}
}
/**
* Description
* @method timeSince
* @param {} date
* @return BinaryExpression
*/
Helpers.timeSince = function(date) {
var seconds = Math.floor((new Date() - date) / 1000)
var interval = Math.floor(seconds / 31536000)
if (interval > 1) {
return interval + 'Y'
}
interval = Math.floor(seconds / 2592000)
if (interval > 1) {
return interval + 'M'
}
interval = Math.floor(seconds / 86400)
if (interval > 1) {
return interval + 'D'
}
interval = Math.floor(seconds / 3600)
if (interval > 1) {
return interval + 'h'
}
interval = Math.floor(seconds / 60)
if (interval > 1) {
return interval + 'm'
}
return Math.floor(seconds) + 's'
}
/**
* Colorize Metrics
*
* @param {Number} value current value
* @param {Number} warn value threshold
* @param {Number} alert value threshold
* @param {String} prefix value prefix
* @return {String} value
*/
Helpers.colorizedMetric = function(value, warn, alert, prefix) {
var inverted = false
if (alert < warn)
inverted = true
if (!prefix) prefix = ''
if (isNaN(value) === true)
return 'N/A'
if (value == 0)
return 0 + prefix
if (inverted == true) {
if (value > warn)
return chalk.green(value + prefix)
if (value <= warn && value >= alert)
return chalk.bold.yellow(value + prefix)
return chalk.bold.red(value + prefix)
}
if (value < warn)
return chalk.green(value + prefix)
if (value >= warn && value <= alert)
return chalk.bold.yellow(value + prefix)
return chalk.bold.red(value + prefix)
}
/**
* Get nested property
*
* @param {String} propertyName
* @param {Object} obj
* @returns {String} property value
*/
Helpers.getNestedProperty = function(propertyName, obj) {
var parts = propertyName.split('.'),
length = parts.length,
property = obj || {}
for (var i = 0; i < length; i++ ) {
property = property[parts[i]]
}
return property
}
Helpers.openEditor = function (file, opts, cb) {
var spawn = require('child_process').spawn
if (typeof opts === 'function') {
cb = opts
opts = {}
}
if (!opts) opts = {}
var ed = /^win/.test(process.platform) ? 'notepad' : 'vim'
var editor = opts.editor || process.env.VISUAL || process.env.EDITOR || ed
var args = editor.split(/\s+/)
var bin = args.shift()
var ps = spawn(bin, args.concat([ file ]), {
windowsHide: true,
stdio: 'inherit'
})
ps.on('exit', function (code, sig) {
if (typeof cb === 'function') cb(code, sig)
})
}
Helpers.dispKeys = function(kv, target_module) {
Object.keys(kv).forEach(function(key) {
if (target_module != null && target_module != key)
return false
if (typeof(kv[key]) == 'object') {
var obj = {}
console.log(chalk.bold('Module: ') + chalk.bold.blue(key))
Object.keys(kv[key]).forEach(function(sub_key) {
console.log(`$ pm2 set ${key}:${sub_key} ${kv[key][sub_key]}`)
})
}
})
}
module.exports = Helpers

9
api.hyungi.net/node_modules/pm2/lib/API/UX/index.js generated vendored Normal file
View File

@@ -0,0 +1,9 @@
const UX = {
helpers: require('./helpers.js'),
describe: require('./pm2-describe.js'),
list: require('./pm2-ls.js'),
list_min: require('./pm2-ls-minimal.js')
}
module.exports = UX

View File

@@ -0,0 +1,193 @@
const Table = require('cli-tableau')
const chalk = require('chalk')
const UxHelpers = require('./helpers.js')
const Common = require('../../Common.js')
var postModuleInfos = function(module_name, human_info) {
var table = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
var disp = {}
human_info.unshift(['Module name', module_name])
human_info.forEach(function(info) {
var obj = {}
obj[chalk.bold.cyan(info[0])] = info[1]
table.push(obj)
})
console.log()
console.log(chalk.bold.inverse(' Module %s infos '), module_name)
console.log(table.toString())
}
/**
* Description
* @method describeTable
* @param {Object} proc process list
*/
module.exports = function(proc) {
var table = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
var pm2_env = proc.pm2_env
var created_at = 'N/A'
if (pm2_env.axm_options && pm2_env.axm_options.human_info) {
postModuleInfos(pm2_env.name, pm2_env.axm_options.human_info)
}
try {
if (pm2_env.created_at != null)
created_at = new Date(pm2_env.created_at).toISOString()
} catch (e) {
}
console.log(chalk.bold.inverse(' Describing process with id %d - name %s '), pm2_env.pm_id, pm2_env.name)
UxHelpers.safe_push(table,
{ 'status' : UxHelpers.colorStatus(pm2_env.status) },
{ 'name': pm2_env.name },
{ 'namespace': pm2_env.namespace },
{ 'version': pm2_env.version },
{ 'restarts' : pm2_env.restart_time },
{ 'uptime' : (pm2_env.pm_uptime && pm2_env.status == 'online') ? UxHelpers.timeSince(pm2_env.pm_uptime) : 0 },
{ 'script path' : pm2_env.pm_exec_path },
{ 'script args' : pm2_env.args ? (typeof pm2_env.args == 'string' ? JSON.parse(pm2_env.args.replace(/'/g, '"')):pm2_env.args).join(' ') : null },
{ 'error log path' : pm2_env.pm_err_log_path },
{ 'out log path' : pm2_env.pm_out_log_path },
{ 'pid path' : pm2_env.pm_pid_path },
{ 'interpreter' : pm2_env.exec_interpreter },
{ 'interpreter args' : pm2_env.node_args.length != 0 ? pm2_env.node_args : null },
{ 'script id' : pm2_env.pm_id },
{ 'exec cwd' : pm2_env.pm_cwd },
{ 'exec mode' : pm2_env.exec_mode },
{ 'node.js version' : pm2_env.node_version },
{ 'node env': pm2_env.env.NODE_ENV },
{ 'watch & reload' : pm2_env.watch ? chalk.green.bold('✔') : '✘' },
{ 'unstable restarts' : pm2_env.unstable_restarts },
{ 'created at' : created_at }
)
if ('pm_log_path' in pm2_env){
table.splice(6, 0, {'entire log path': pm2_env.pm_log_path})
}
if ('cron_restart' in pm2_env){
table.splice(5, 0, {'cron restart': pm2_env.cron_restart})
}
console.log(table.toString())
/**
* Module conf display
*/
if (pm2_env.axm_options &&
pm2_env.axm_options.module_conf &&
Object.keys(pm2_env.axm_options.module_conf).length > 0) {
var table_conf = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
console.log('Process configuration')
Object.keys(pm2_env.axm_options.module_conf).forEach(function(key) {
var tmp = {}
tmp[key] = pm2_env.axm_options.module_conf[key]
UxHelpers.safe_push(table_conf, tmp)
})
console.log(table_conf.toString())
}
/**
* Versioning metadata
*/
if (pm2_env.versioning) {
var table2 = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
console.log(chalk.inverse.bold(' Revision control metadata '))
UxHelpers.safe_push(table2,
{ 'revision control' : pm2_env.versioning.type },
{ 'remote url' : pm2_env.versioning.url },
{ 'repository root' : pm2_env.versioning.repo_path },
{ 'last update' : pm2_env.versioning.update_time },
{ 'revision' : pm2_env.versioning.revision },
{ 'comment' : pm2_env.versioning.comment ? pm2_env.versioning.comment.trim().slice(0, 60) : '' },
{ 'branch' : pm2_env.versioning.branch }
)
console.log(table2.toString())
}
if (pm2_env.axm_actions && Object.keys(pm2_env.axm_actions).length > 0) {
var table_actions = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
console.log(chalk.inverse.bold(' Actions available '))
pm2_env.axm_actions.forEach(function(action_set) {
UxHelpers.safe_push(table_actions, [action_set.action_name])
})
console.log(table_actions.toString())
Common.printOut(chalk.white.italic(' Trigger via: pm2 trigger %s <action_name>\n'), pm2_env.name)
}
if (pm2_env.axm_monitor && Object.keys(pm2_env.axm_monitor).length > 0) {
var table_probes = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
console.log(chalk.inverse.bold(' Code metrics value '))
Object.keys(pm2_env.axm_monitor).forEach(function(key) {
var obj = {}
var metric_name = pm2_env.axm_monitor[key].hasOwnProperty("value") ? pm2_env.axm_monitor[key].value : pm2_env.axm_monitor[key]
var metric_unit = pm2_env.axm_monitor[key].hasOwnProperty("unit") ? pm2_env.axm_monitor[key].unit : ''
var value = `${metric_name} ${metric_unit}`
obj[key] = value
UxHelpers.safe_push(table_probes, obj)
})
console.log(table_probes.toString())
}
var table_env = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
console.log(chalk.inverse.bold(' Divergent env variables from local env '))
var _env = Common.safeExtend({}, pm2_env)
var diff_env = {}
Object.keys(process.env).forEach(k => {
if (!_env[k] || _env[k] != process.env[k]) {
diff_env[k] = process.env[k]
}
})
Object.keys(diff_env).forEach(function(key) {
var obj = {}
if (_env[key]) {
// 1. fix env value is not a String and slice is undeinfed
// 2. fix process.stdout.columns is undefined and causes empty string output
// 3. columns defaults to 300 - same as specified in pm2-ls
obj[key] = String(_env[key]).slice(0, (process.stdout.columns || 300) - 60)
UxHelpers.safe_push(table_env, obj)
}
})
console.log(table_env.toString())
console.log()
Common.printOut(chalk.white.italic(' Add your own code metrics: http://bit.ly/code-metrics'))
Common.printOut(chalk.white.italic(' Use `pm2 logs %s [--lines 1000]` to display logs'), pm2_env.name)
Common.printOut(chalk.white.italic(' Use `pm2 env %s` to display environment variables'), pm2_env.pm_id)
Common.printOut(chalk.white.italic(' Use `pm2 monit` to monitor CPU and Memory usage'), pm2_env.name)
}

View File

@@ -0,0 +1,31 @@
const UxHelpers = require('./helpers.js')
const p = require('path')
/**
* Minimal display via pm2 ls -m
* @method miniDisplay
* @param {Object} list process list
*/
module.exports = function(list) {
list.forEach(function(l) {
var mode = l.pm2_env.exec_mode.split('_mode')[0]
var status = l.pm2_env.status
var key = l.pm2_env.name || p.basename(l.pm2_env.pm_exec_path.script)
console.log('+--- %s', key)
console.log('namespace : %s', l.pm2_env.namespace)
console.log('version : %s', l.pm2_env.version)
console.log('pid : %s', l.pid)
console.log('pm2 id : %s', l.pm2_env.pm_id)
console.log('status : %s', status)
console.log('mode : %s', mode)
console.log('restarted : %d', l.pm2_env.restart_time ? l.pm2_env.restart_time : 0)
console.log('uptime : %s', (l.pm2_env.pm_uptime && status == 'online') ? UxHelpers.timeSince(l.pm2_env.pm_uptime) : 0)
console.log('memory usage : %s', l.monit ? UxHelpers.bytesToSize(l.monit.memory, 1) : '')
console.log('error log : %s', l.pm2_env.pm_err_log_path)
console.log('watching : %s', l.pm2_env.watch ? 'yes' : 'no')
console.log('PID file : %s\n', l.pm2_env.pm_pid_path)
})
}

482
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-ls.js generated vendored Normal file
View File

@@ -0,0 +1,482 @@
const cst = require('../../../constants')
const Common = require('../../Common')
const Configuration = require('../../Configuration')
const UxHelpers = require('./helpers.js')
const chalk = require('chalk')
const Table = require('cli-tableau')
const Passwd = require('../../tools/passwd.js')
const List = {}
const CONDENSED_MODE = (process.stdout.columns || 300) < 134
/**
* Check if dump file contains same apps that the one managed by PM2
*/
function checkIfProcessAreDumped(list) {
try {
var dump_raw = require('fs').readFileSync(cst.DUMP_FILE_PATH)
var dump = JSON.parse(dump_raw)
var apps_dumped = dump.map(proc => proc.name)
var apps_running = list
.filter(proc => proc.pm2_env.pmx_module != true)
.map(proc => proc.name)
var diff = apps_dumped.filter(a => !apps_running.includes(a))
if (diff.length > 0) {
Common.warn(`Current process list is not synchronized with saved list. App ${chalk.bold(diff.join(' '))} differs. Type 'pm2 save' to synchronize.`)
}
else if (apps_dumped.length != apps_running.length) {
Common.warn(`Current process list is not synchronized with saved list. Type 'pm2 save' to synchronize.`)
}
} catch(e) {
}
}
var proc_id = 0
/**
* List Applications and Modules managed by PM2
*/
function listModulesAndAppsManaged(list, commander) {
var name_col_size = 11
if (list && list.length > 0)
name_col_size = (list.reduce((p, c) => (p.name.length > c.name.length) ? p : c)).name.length + 5
var id_width = Math.max(
2 + (Math.max(...list.map((l) => String(l.pm2_env.pm_id || 0).length)) || 0),
4
);
var app_head = {
id: id_width,
name: name_col_size,
namespace: 13,
version: 9,
mode: 9,
pid: 10,
uptime: 8,
'↺': 6,
status: 11,
cpu: 10,
mem: 10,
user: 10,
watching: 10
}
var mod_head = {
id: id_width,
module: 30,
version: 15,
pid: 10,
status: 10,
'↺': 6,
cpu: 10,
mem: 10,
user: 10
}
if (CONDENSED_MODE) {
app_head = {
id: id_width,
name: 20,
mode: 10,
'↺': 6,
status: 11,
cpu: 10,
memory: 10
}
mod_head = {
id: id_width,
name: 20,
status: 10,
cpu: 10,
mem: 10
}
}
var app_table = new Table({
head : Object.keys(app_head),
colWidths: Object.keys(app_head).map(k => app_head[k]),
colAligns : ['left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
var module_table = new Table({
head : Object.keys(mod_head),
colWidths: Object.keys(mod_head).map(k => mod_head[k]),
colAligns : ['left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
var sortField = 'name', sortOrder = 'asc', sort,
fields = {
name: 'pm2_env.name',
namespace: 'pm2_env.namespace',
pid: 'pid',
id: 'pm_id',
cpu: 'monit.cpu',
memory: 'monit.memory',
uptime: 'pm2_env.pm_uptime',
status: 'pm2_env.status'
}
if (commander && commander.sort) {
sort = commander.sort.split(':');
if(fields[sort[0].toLowerCase()]) {
sortField = sort[0].toLowerCase();
sortOrder = sort.length === 2 ? sort[1] : 'asc';
}
}
list.sort(function(a, b) {
var fieldA = UxHelpers.getNestedProperty(fields[sortField], a)
var fieldB = UxHelpers.getNestedProperty(fields[sortField], b)
if (sortOrder === 'desc') {
if (fieldA > fieldB)
return -1
if (fieldA < fieldB)
return 1
} else {
if (fieldA < fieldB)
return -1
if (fieldA > fieldB)
return 1
}
return 0
})
list.forEach(function(l) {
var obj = {}
if (l.pm2_env.pm_id > proc_id) {
proc_id = l.pm2_env.pm_id
}
var mode = l.pm2_env.exec_mode
var status = l.pm2_env.status
var key = l.pm2_env.pm_id
key = chalk.bold.cyan(key)
if (l.pm2_env.axm_options) {
var is_tracing_enabled = false
if (l.pm2_env.axm_options.tracing &&
typeof(l.pm2_env.axm_options.tracing) == 'boolean' &&
l.pm2_env.axm_options.tracing == true)
is_tracing_enabled = true
if (l.pm2_env.axm_options.tracing &&
l.pm2_env.axm_options.tracing.enabled &&
typeof(l.pm2_env.axm_options.tracing.enabled) == 'boolean' &&
l.pm2_env.axm_options.tracing.enabled == true)
is_tracing_enabled = true
if (is_tracing_enabled == true)
l.pm2_env.name = chalk.green('☵') + ' ' + l.pm2_env.name
if (l.pm2_env._km_monitored)
l.pm2_env.name = chalk.bold.green('◉') + ' ' + l.pm2_env.name
}
if (l.pm2_env.pmx_module == true) {
if (l.pm2_env.name == 'pm2-sysmonit') return
// pm2 ls for Modules
obj[key] = []
obj[key].push(l.name)
// Module version + PID
if (!CONDENSED_MODE) {
var pid = l.pm2_env.axm_options.pid ? l.pm2_env.axm_options.pid : l.pid
obj[key].push(l.pm2_env.version || 'N/A', pid)
}
// Status
obj[key].push(UxHelpers.colorStatus(status))
// Restart
if (!CONDENSED_MODE)
obj[key].push(l.pm2_env.restart_time ? l.pm2_env.restart_time : 0)
// CPU + Memory
obj[key].push(l.monit ? (l.monit.cpu + '%') : 'N/A', l.monit ? UxHelpers.bytesToSize(l.monit.memory, 1) : 'N/A' )
// User
if (!CONDENSED_MODE) {
if (l.pm2_env.uid && typeof(l.pm2_env.uid) == 'number') {
// Resolve user id to username
let users = Passwd.getUsers()
Object.keys(users).forEach(function(username) {
var user = users[username]
if (user.userId == l.pm2_env.uid) {
l.pm2_env.uid = user.username
}
})
}
obj[key].push(chalk.bold(l.pm2_env.uid || l.pm2_env.username))
}
UxHelpers.safe_push(module_table, obj)
}
else {
// pm2 ls for Applications
obj[key] = []
// PM2 ID
obj[key].push(l.pm2_env.name)
// Namespace
if (!CONDENSED_MODE)
obj[key].push(l.pm2_env.namespace)
// Version
if (!CONDENSED_MODE)
obj[key].push(l.pm2_env.version)
// Exec mode
obj[key].push(mode == 'fork_mode' ? chalk.inverse.bold('fork') : chalk.blue.bold('cluster'))
// PID
if (!CONDENSED_MODE)
obj[key].push(l.pid)
// Uptime
if (!CONDENSED_MODE)
obj[key].push((l.pm2_env.pm_uptime && status == 'online') ? UxHelpers.timeSince(l.pm2_env.pm_uptime) : 0)
// Restart
obj[key].push(l.pm2_env.restart_time ? l.pm2_env.restart_time : 0)
// Status
obj[key].push(UxHelpers.colorStatus(status))
// CPU
obj[key].push(l.monit ? l.monit.cpu + '%' : 'N/A')
// Memory
obj[key].push(l.monit ? UxHelpers.bytesToSize(l.monit.memory, 1) : 'N/A')
// User
if (!CONDENSED_MODE) {
if (l.pm2_env.uid && typeof(l.pm2_env.uid) == 'number') {
// Resolve user id to username
let users = Passwd.getUsers()
Object.keys(users).forEach(function(username) {
var user = users[username]
if (user.userId == l.pm2_env.uid) {
l.pm2_env.uid = user.username
}
})
}
obj[key].push(chalk.bold(l.pm2_env.uid || l.pm2_env.username))
}
// Watch status
if (!CONDENSED_MODE)
obj[key].push(l.pm2_env.watch ? chalk.green.bold('enabled') : chalk.grey('disabled'))
UxHelpers.safe_push(app_table, obj)
}
})
// Print Applications Managed
console.log(app_table.toString())
// Print Modules Managed
if (module_table.length > 0) {
console.log(chalk.bold(`Module${module_table.length > 1 ? 's' : ''}`))
console.log(module_table.toString())
}
proc_id++
}
// Container display
function containersListing(sys_infos) {
var stacked_docker = (process.stdout.columns || 100) < 140
var docker_head = {
id: 4,
image: 50,
status: 10,
'↺': 6,
cpu: 10,
mem: 10,
'net I/O ⇵': 11,
'fs I/O ⇵': 11
}
if (stacked_docker) {
docker_head = {
id: 4,
image: 25,
status: 10,
cpu: 10,
mem: 10
}
}
var docker_table = new Table({
colWidths: Object.keys(docker_head).map(k => docker_head[k]),
head : Object.keys(docker_head),
colAligns : ['left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
sys_infos.containers.forEach((c) => {
var cpu = c.stats.cpu_percent
var mem = c.stats.mem_percent == 0 ? '0' : c.stats.mem_percent
var id = chalk.bold.cyan(proc_id++)
var state = UxHelpers.colorStatus(c.state)
if (stacked_docker)
docker_table.push([id, c.image, state, `${cpu}%`, `${mem}mb`])
else {
docker_table.push([
id,
c.image,
state,
c.restartCount,
`${cpu == 0 ? '0' : cpu}%`,
`${mem}mb`,
`${c.stats.netIO.rx}/${isNaN(c.stats.netIO.tx) == true ? '0.0' : c.stats.netIO.tx}`,
`${c.stats.blockIO.r}/${c.stats.blockIO.w}`
])
}
})
console.log(chalk.bold(`Container${sys_infos.containers.length > 1 ? 's' : ''}`))
console.log(docker_table.toString())
}
/**
* High resource processes
*/
function listHighResourcesProcesses(sys_infos) {
const CPU_MIN_SHOW = 60
const MEM_MIN_SHOW = 30
var sys_proc_head = ['id', 'cmd', 'pid', 'cpu', 'mem', 'uid']
var sys_proc_table = new Table({
colWidths: [4, CONDENSED_MODE ? 29 : 77, 10, 10, 10, 8],
head : sys_proc_head,
colAligns : ['left'],
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true}
})
sys_infos.processes.cpu_sorted = sys_infos.processes.cpu_sorted.filter((proc) => {
return proc.cpu > CPU_MIN_SHOW && proc.cmd.includes('node') === false &&
proc.cmd.includes('God Daemon') === false
})
sys_infos.processes.cpu_sorted.forEach(proc => {
var cpu = `${UxHelpers.colorizedMetric(proc.cpu, 40, 70, '%')}`
var mem = `${UxHelpers.colorizedMetric(proc.memory, 40, 70, '%')}`
var cmd = proc.cmd
sys_proc_table.push([chalk.bold.cyan(proc_id++), cmd, proc.pid, cpu, mem, proc.uid])
})
sys_infos.processes.mem_sorted = sys_infos.processes.mem_sorted.filter((proc) => {
return proc.memory > MEM_MIN_SHOW && proc.cmd.includes('node') == false
})
sys_infos.processes.mem_sorted.forEach((proc) => {
var cpu = `${UxHelpers.colorizedMetric(proc.cpu, 40, 70, '%')}`
var mem = `${UxHelpers.colorizedMetric(proc.memory, 40, 70, '%')}`
var cmd = proc.cmd
// if (proc.cmd.length > 50)
// cmd = '…' + proc.cmd.slice(proc.cmd.length - 48, proc.cmd.length)
sys_proc_table.push([chalk.bold.cyan(proc_id++), cmd, proc.pid, cpu, mem, proc.uid])
})
if (sys_infos.processes.cpu_sorted.length >= 1 || sys_infos.processes.mem_sorted.length >= 1) {
console.log(chalk.bold('Intensive Processes'))
console.log(sys_proc_table.toString())
}
}
/**
* Sys info line
*/
function miniMonitBar(sys_infos) {
let sys_metrics = sys_infos.pm2_env.axm_monitor
let cpu = sys_metrics['CPU Usage']
if (typeof(cpu) == 'undefined') return
var sys_summary_line = `${chalk.bold.cyan('host metrics')} `
sys_summary_line += `| ${chalk.bold('cpu')}: ${UxHelpers.colorizedMetric(cpu.value, 40, 70, '%')}`
let temp = sys_metrics['CPU Temperature'].value
if (temp && temp != '-1') {
sys_summary_line += ` ${UxHelpers.colorizedMetric(temp, 50, 70, 'º')}`
}
let mem_total = sys_metrics['RAM Total'].value
let mem_available = sys_metrics['RAM Available'].value
if (mem_total) {
var perc_mem_usage = (((mem_available) / mem_total) * 100).toFixed(1)
sys_summary_line += ` | ${chalk.bold('mem free')}: ${UxHelpers.colorizedMetric(perc_mem_usage, 30, 10, '%')} `
}
let interfaces = Object.keys(sys_metrics).filter(m => m.includes('net') && m != 'net:default').map(i => i.split(':')[2]).filter((iface, i, self) => self.indexOf(iface) === i)
interfaces.forEach(iface => {
if (!sys_metrics[`net:rx_5:${iface}`]) return
sys_summary_line += `| ${chalk.bold(iface)}: `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_metrics[`net:rx_5:${iface}`].value, 10, 20, 'mb/s')} `
sys_summary_line += `${UxHelpers.colorizedMetric(sys_metrics[`net:tx_5:${iface}`].value, 10, 20, 'mb/s')} `
})
if (CONDENSED_MODE == false) {
let read = sys_metrics['Disk Reads'].value
let write = sys_metrics['Disk Writes'].value
sys_summary_line += `| ${chalk.bold('disk')}: ⇓ ${UxHelpers.colorizedMetric(read, 10, 20, 'mb/s')}`
sys_summary_line += `${UxHelpers.colorizedMetric(write, 10, 20, 'mb/s')} `
let disks = Object.keys(sys_metrics).filter(m => m.includes('fs:')).map(i => i.split(':')[2]).filter((iface, i, self) => self.indexOf(iface) === i)
var disk_nb = 0
disks.forEach(fs => {
let use = sys_metrics[`fs:use:${fs}`].value
if (use > 60)
sys_summary_line += `${chalk.grey(fs)} ${UxHelpers.colorizedMetric(use, 80, 90, '%')} `
})
}
sys_summary_line += '|'
console.log(sys_summary_line)
}
/**
* pm2 ls
* @method dispAsTable
* @param {Object} list
* @param {Object} system informations (via pm2 sysmonit/pm2 sysinfos)
*/
module.exports = function(list, commander) {
var pm2_conf = Configuration.getSync('pm2')
if (!list)
return console.log('list empty')
listModulesAndAppsManaged(list, commander)
let sysmonit = list.filter(proc => proc.name == 'pm2-sysmonit')
if (sysmonit && sysmonit[0])
miniMonitBar(sysmonit[0])
checkIfProcessAreDumped(list)
}

382
api.hyungi.net/node_modules/pm2/lib/API/Version.js generated vendored Normal file
View File

@@ -0,0 +1,382 @@
var cst = require('../../constants.js');
var Common = require('../Common.js');
var fs = require('fs');
var eachSeries = require('async/eachSeries');
var child = require('child_process');
var printError = Common.printError;
var printOut = Common.printOut;
module.exports = function(CLI) {
var EXEC_TIMEOUT = 60000; // Default: 1 min
CLI.prototype._pull = function(opts, cb) {
var that = this;
var process_name = opts.process_name;
var reload_type = opts.action;
printOut(cst.PREFIX_MSG + 'Updating repository for process name %s', process_name);
that.Client.getProcessByNameOrId(process_name, function (err, processes) {
if (err || processes.length === 0) {
printError('No processes with this name or id : %s', process_name);
return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
}
var proc = processes[0];
if (!proc.pm2_env.versioning) {
printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
return cb ? cb({success:false, msg: 'No versioning system found for process'}) : that.exitCli(cst.SUCCESS_EXIT);
}
require('vizion').update({
folder: proc.pm2_env.versioning.repo_path
}, function(err, meta) {
if (err !== null) {
return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
}
if (meta.success === true) {
getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
if (err !== null) {
printError(err);
return cb ? cb({msg: meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
}
else {
printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
return that[reload_type](process_name, function(err, procs) {
if (err && cb) return cb(err);
if (err) console.error(err);
return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
});
}
});
});
}
else {
printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured for app: %s', process_name);
return cb ? cb({success:false, msg : 'Already up to date'}) : that.exitCli(cst.SUCCESS_EXIT);
}
return false;
});
return false;
});
};
/**
* CLI method for updating a repository to a specific commit id
* @method pullCommitId
* @param {string} process_name
* @param {string} commit_id
* @return
*/
CLI.prototype.pullCommitId = function(process_name, commit_id, cb) {
var reload_type = 'reload';
var that = this;
printOut(cst.PREFIX_MSG + 'Updating repository for process name %s', process_name);
that.Client.getProcessByNameOrId(process_name, function (err, processes) {
if (err || processes.length === 0) {
printError('No processes with this name or id : %s', process_name);
return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
}
var proc = processes[0];
if (proc.pm2_env.versioning) {
require('vizion').isUpToDate({folder: proc.pm2_env.versioning.repo_path}, function(err, meta) {
if (err !== null)
return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
require('vizion').revertTo(
{revision: commit_id,
folder: proc.pm2_env.versioning.repo_path},
function(err2, meta2) {
if (!err2 && meta2.success) {
getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
if (err !== null)
{
printError(err);
return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
}
else {
printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
printOut(cst.PREFIX_MSG + 'Current commit %s', commit_id);
return that[reload_type](process_name, cb);
}
});
});
}
else {
printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured: %s', process_name);
return cb ? cb(null, {success:meta.success}) : that.exitCli(cst.SUCCESS_EXIT);
}
});
});
}
else {
printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
return cb ? cb(null, {success:false}) : that.exitCli(cst.SUCCESS_EXIT);
}
});
};
/**
* CLI method for downgrading a repository to the previous commit (older)
* @method backward
* @param {string} process_name
* @return
*/
CLI.prototype.backward = function(process_name, cb) {
var that = this;
printOut(cst.PREFIX_MSG + 'Downgrading to previous commit repository for process name %s', process_name);
that.Client.getProcessByNameOrId(process_name, function (err, processes) {
if (err || processes.length === 0) {
printError('No processes with this name or id : %s', process_name);
return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
}
var proc = processes[0];
// in case user searched by id/pid
process_name = proc.name;
if (proc.pm2_env.versioning === undefined ||
proc.pm2_env.versioning === null)
return cb({msg : 'Versioning unknown'});
require('vizion').prev({
folder: proc.pm2_env.versioning.repo_path
}, function(err, meta) {
if (err)
return cb ? cb({msg:err, data : meta}) : that.exitCli(cst.ERROR_EXIT);
if (meta.success !== true) {
printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
return cb ? cb({msg:err, data : meta}) : that.exitCli(cst.ERROR_EXIT);
}
getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
if (err !== null) {
require('vizion').next({folder: proc.pm2_env.versioning.repo_path}, function(err2, meta2) {
printError(err);
return cb ? cb({msg: meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
});
return false;
}
printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
that.reload(process_name, function(err, procs) {
if (err) return cb(err);
return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
});
});
});
});
});
};
/**
* CLI method for updating a repository to the next commit (more recent)
* @method forward
* @param {string} process_name
* @return
*/
CLI.prototype.forward = function(process_name, cb) {
var that = this;
printOut(cst.PREFIX_MSG + 'Updating to next commit repository for process name %s', process_name);
that.Client.getProcessByNameOrId(process_name, function (err, processes) {
if (err || processes.length === 0) {
printError('No processes with this name or id: %s', process_name);
return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
}
var proc = processes[0];
// in case user searched by id/pid
process_name = proc.name;
if (proc.pm2_env.versioning) {
require('vizion').next({folder: proc.pm2_env.versioning.repo_path}, function(err, meta) {
if (err !== null)
return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
if (meta.success === true) {
getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
if (err !== null)
{
require('vizion').prev({folder: proc.pm2_env.versioning.repo_path}, function(err2, meta2) {
printError(err);
return cb ? cb({msg:meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
});
}
else {
printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
that.reload(process_name, function(err, procs) {
if (err) return cb(err);
return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
});
}
});
});
}
else {
printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured: %s', process_name);
return cb ? cb(null, {success:meta.success}) : that.exitCli(cst.SUCCESS_EXIT);
}
});
}
else {
printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
return cb ? cb({success:false, msg: 'No versioning system found'}) : that.exitCli(cst.SUCCESS_EXIT);
}
});
};
var exec = function (cmd, callback) {
var output = '';
var c = child.exec(cmd, {
env: process.env,
maxBuffer: 3*1024*1024,
timeout: EXEC_TIMEOUT
}, function(err) {
if (callback)
callback(err ? err.code : 0, output);
});
c.stdout.on('data', function(data) {
output += data;
});
c.stderr.on('data', function(data) {
output += data;
});
};
/**
*
* @method execCommands
* @param {string} repo_path
* @param {object} command_list
* @return
*/
var execCommands = function(repo_path, command_list, cb) {
var stdout = '';
eachSeries(command_list, function(command, callback) {
stdout += '\n' + command;
exec('cd '+repo_path+';'+command,
function(code, output) {
stdout += '\n' + output;
if (code === 0)
callback();
else
callback('`'+command+'` failed');
});
}, function(err) {
if (err)
return cb(stdout + '\n' + err);
return cb(null, stdout);
});
}
/**
* Description Search process.json for post-update commands
* @method getPostUpdateCmds
* @param {string} repo_path
* @param {string} proc_name
* @return
*/
var getPostUpdateCmds = function(repo_path, proc_name, cb) {
if (typeof repo_path !== 'string')
return cb([]);
if (repo_path[repo_path.length - 1] !== '/')
repo_path += '/';
var searchForCommands = function(file, callback) {
fs.exists(repo_path+file, function(exists) {
if (exists) {
try {
var conf_string = fs.readFileSync(repo_path + file);
var data = Common.parseConfig(conf_string, repo_path + file);
} catch (e) {
console.error(e.message || e);
}
if (data && data.apps) {
eachSeries(data.apps, function(item, callb) {
if (item.name && item.name === proc_name) {
if (item.post_update && typeof(item.post_update) === 'object') {
if (item.exec_timeout)
EXEC_TIMEOUT = parseInt(item.exec_timeout);
return callb(item.post_update);
}
else {
return callb();
}
}
else
return callb();
}, function(final) {
return callback(final);
});
}
else {
return callback();
}
}
else {
return callback();
}
});
};
eachSeries(['ecosystem.json', 'process.json', 'package.json'], searchForCommands,
function(final) {
return cb(final ? final : []);
});
};
/**
* CLI method for updating a repository
* @method pullAndRestart
* @param {string} process_name name of processes to pull
* @return
*/
CLI.prototype.pullAndRestart = function (process_name, cb) {
this._pull({process_name: process_name, action: 'reload'}, cb);
};
/**
* CLI method for updating a repository
* @method pullAndReload
* @param {string} process_name name of processes to pull
* @return
*/
CLI.prototype.pullAndReload = function (process_name, cb) {
this._pull({process_name: process_name, action: 'reload'}, cb);
};
/**
* CLI method for updating a repository to a specific commit id
* @method pullCommitId
* @param {object} opts
* @return
*/
CLI.prototype._pullCommitId = function (opts, cb) {
this.pullCommitId(opts.pm2_name, opts.commit_id, cb);
};
}

View File

@@ -0,0 +1,12 @@
{
".sh" : "bash",
".py" : "python",
".rb" : "ruby",
".php" : "php",
".pl" : "perl",
".js" : "node",
".coffee" : "coffee",
".ls" : "lsc",
".ts" : "bun",
".tsx" : "bun"
}

View File

@@ -0,0 +1,372 @@
'use strict'
var cst = require('../../../constants.js');
const chalk = require('chalk');
const path = require('path');
const fs = require('fs');
const Table = require('cli-tableau');
const pkg = require('../../../package.json')
const IOAPI = require('@pm2/js-api')
const promptly = require('promptly')
var CLIStrategy = require('./auth-strategies/CliAuth')
var WebStrategy = require('./auth-strategies/WebAuth')
const exec = require('child_process').exec
const OAUTH_CLIENT_ID_WEB = '138558311'
const OAUTH_CLIENT_ID_CLI = '0943857435'
module.exports = class PM2ioHandler {
static usePM2Client (instance) {
this.pm2 = instance
}
static strategy () {
switch (process.platform) {
case 'darwin': {
return new WebStrategy({
client_id: OAUTH_CLIENT_ID_WEB
})
}
case 'win32': {
return new WebStrategy({
client_id: OAUTH_CLIENT_ID_WEB
})
}
case 'linux': {
const isDesktop = process.env.XDG_CURRENT_DESKTOP || process.env.XDG_SESSION_DESKTOP || process.env.DISPLAY
const isSSH = process.env.SSH_TTY || process.env.SSH_CONNECTION
if (isDesktop && !isSSH) {
return new WebStrategy({
client_id: OAUTH_CLIENT_ID_WEB
})
} else {
return new CLIStrategy({
client_id: OAUTH_CLIENT_ID_CLI
})
}
}
default: {
return new CLIStrategy({
client_id: OAUTH_CLIENT_ID_CLI
})
}
}
}
static init () {
this._strategy = this.strategy()
/**
* If you are using a local backend you should give those options :
* {
* services: {
* API: 'http://localhost:3000',
* OAUTH: 'http://localhost:3100'
* }
* }
*/
this.io = new IOAPI().use(this._strategy)
}
static launch (command, opts) {
// first init the strategy and the io client
this.init()
switch (command) {
case 'connect' :
case 'login' :
case 'register' :
case undefined :
case 'authenticate' : {
this.authenticate()
break
}
case 'validate' : {
this.validateAccount(opts)
break
}
case 'help' :
case 'welcome': {
var dt = fs.readFileSync(path.join(__dirname, './pres/welcome'));
console.log(dt.toString());
return process.exit(0)
}
case 'logout': {
this._strategy.isAuthenticated().then(isConnected => {
// try to kill the agent anyway
this.pm2.killAgent(err => {})
if (isConnected === false) {
console.log(`${cst.PM2_IO_MSG} Already disconnected`)
return process.exit(0)
}
this._strategy._retrieveTokens((err, tokens) => {
if (err) {
console.log(`${cst.PM2_IO_MSG} Successfully disconnected`)
return process.exit(0)
}
this._strategy.deleteTokens(this.io).then(_ => {
console.log(`${cst.PM2_IO_MSG} Successfully disconnected`)
return process.exit(0)
}).catch(err => {
console.log(`${cst.PM2_IO_MSG_ERR} Unexpected error: ${err.message}`)
return process.exit(1)
})
})
}).catch(err => {
console.error(`${cst.PM2_IO_MSG_ERR} Failed to logout: ${err.message}`)
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
})
break
}
case 'create': {
this._strategy.isAuthenticated().then(res => {
// if the user isn't authenticated, we make them do the whole flow
if (res !== true) {
this.authenticate()
} else {
this.createBucket(this.createBucketHandler.bind(this))
}
}).catch(err => {
console.error(`${cst.PM2_IO_MSG_ERR} Failed to create to the bucket: ${err.message}`)
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
})
break
}
case 'web': {
this._strategy.isAuthenticated().then(res => {
// if the user isn't authenticated, we make them do the whole flow
if (res === false) {
console.error(`${cst.PM2_IO_MSG_ERR} You need to be authenticated to do that, please use: pm2 plus login`)
return process.exit(1)
}
this._strategy._retrieveTokens(() => {
return this.openUI()
})
}).catch(err => {
console.error(`${cst.PM2_IO_MSG_ERR} Failed to open the UI: ${err.message}`)
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
})
break
}
default : {
console.log(`${cst.PM2_IO_MSG_ERR} Invalid command ${command}, available : login,register,validate,connect or web`)
process.exit(1)
}
}
}
static openUI () {
this.io.bucket.retrieveAll().then(res => {
const buckets = res.data
if (buckets.length === 0) {
return this.createBucket((err, bucket) => {
if (err) {
console.error(`${cst.PM2_IO_MSG_ERR} Failed to connect to the bucket: ${err.message}`)
if (bucket) {
console.error(`${cst.PM2_IO_MSG_ERR} You can retry using: pm2 plus link ${bucket.secret_id} ${bucket.public_id}`)
}
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
return process.exit(0)
}
const targetURL = `https://app.pm2.io/#/bucket/${bucket._id}`
console.log(`${cst.PM2_IO_MSG} Please follow the popup or go to this URL :`, '\n', ' ', targetURL)
this.open(targetURL)
return process.exit(0)
})
}
var table = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true},
head : ['Bucket name', 'Plan type']
})
buckets.forEach(function(bucket) {
table.push([bucket.name, bucket.credits.offer_type])
})
console.log(table.toString())
console.log(`${cst.PM2_IO_MSG} If you don't want to open the UI to a bucket, type 'none'`)
const choices = buckets.map(bucket => bucket.name)
choices.push('none')
promptly.choose(`${cst.PM2_IO_MSG} Type the name of the bucket you want to connect to :`, choices, (err, value) => {
if (value === 'none') process.exit(0)
const bucket = buckets.find(bucket => bucket.name === value)
if (bucket === undefined) return process.exit(0)
const targetURL = `https://app.pm2.io/#/bucket/${bucket._id}`
console.log(`${cst.PM2_IO_MSG} Please follow the popup or go to this URL :`, '\n', ' ', targetURL)
this.open(targetURL)
return process.exit(0)
})
})
}
static validateAccount (token) {
this.io.auth.validEmail(token)
.then(res => {
console.log(`${cst.PM2_IO_MSG} Email succesfully validated.`)
console.log(`${cst.PM2_IO_MSG} You can now proceed and use: pm2 plus connect`)
return process.exit(0)
}).catch(err => {
if (err.status === 401) {
console.error(`${cst.PM2_IO_MSG_ERR} Invalid token`)
return process.exit(1)
} else if (err.status === 301) {
console.log(`${cst.PM2_IO_MSG} Email succesfully validated.`)
console.log(`${cst.PM2_IO_MSG} You can now proceed and use: pm2 plus connect`)
return process.exit(0)
}
const msg = err.data ? err.data.error_description || err.data.msg : err.message
console.error(`${cst.PM2_IO_MSG_ERR} Failed to validate your email: ${msg}`)
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
return process.exit(1)
})
}
static createBucketHandler (err, bucket) {
if (err) {
console.trace(`${cst.PM2_IO_MSG_ERR} Failed to connect to the bucket: ${err.message}`)
if (bucket) {
console.error(`${cst.PM2_IO_MSG_ERR} You can retry using: pm2 plus link ${bucket.secret_id} ${bucket.public_id}`)
}
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
return process.exit(0)
}
if (bucket === undefined) {
return process.exit(0)
}
console.log(`${cst.PM2_IO_MSG} Successfully connected to bucket ${bucket.name}`)
var targetURL = `https://app.pm2.io/#/bucket/${bucket._id}`
console.log(`${cst.PM2_IO_MSG} You can use the web interface over there: ${targetURL}`)
this.open(targetURL)
return process.exit(0)
}
static createBucket (cb) {
console.log(`${cst.PM2_IO_MSG} By default we allow you to trial PM2 Plus for 14 days without any credit card.`)
this.io.bucket.create({
name: 'PM2 Plus Monitoring'
}).then(res => {
const bucket = res.data.bucket
console.log(`${cst.PM2_IO_MSG} Successfully created the bucket`)
this.pm2.link({
public_key: bucket.public_id,
secret_key: bucket.secret_id,
pm2_version: pkg.version
}, (err) => {
if (err) {
return cb(new Error('Failed to connect your local PM2 to your bucket'), bucket)
} else {
return cb(null, bucket)
}
})
}).catch(err => {
return cb(new Error(`Failed to create a bucket: ${err.message}`))
})
}
/**
* Connect the local agent to a specific bucket
* @param {Function} cb
*/
static connectToBucket (cb) {
this.io.bucket.retrieveAll().then(res => {
const buckets = res.data
if (buckets.length === 0) {
return this.createBucket(cb)
}
var table = new Table({
style : {'padding-left' : 1, head : ['cyan', 'bold'], compact : true},
head : ['Bucket name', 'Plan type']
})
buckets.forEach(function(bucket) {
table.push([bucket.name, bucket.payment.offer_type])
})
console.log(table.toString())
console.log(`${cst.PM2_IO_MSG} If you don't want to connect to a bucket, type 'none'`)
const choices = buckets.map(bucket => bucket.name)
choices.push('none')
promptly.choose(`${cst.PM2_IO_MSG} Type the name of the bucket you want to connect to :`, choices, (err, value) => {
if (value === 'none') return cb()
const bucket = buckets.find(bucket => bucket.name === value)
if (bucket === undefined) return cb()
this.pm2.link({
public_key: bucket.public_id,
secret_key: bucket.secret_id,
pm2_version: pkg.version
}, (err) => {
return err ? cb(err) : cb(null, bucket)
})
})
})
}
/**
* Authenticate the user with either of the strategy
* @param {Function} cb
*/
static authenticate () {
this._strategy._retrieveTokens((err, tokens) => {
if (err) {
const msg = err.data ? err.data.error_description || err.data.msg : err.message
console.log(`${cst.PM2_IO_MSG_ERR} Unexpected error : ${msg}`)
return process.exit(1)
}
console.log(`${cst.PM2_IO_MSG} Successfully authenticated`)
this.io.user.retrieve().then(res => {
const user = res.data
this.io.user.retrieve().then(res => {
const tmpUser = res.data
console.log(`${cst.PM2_IO_MSG} Successfully validated`)
this.connectToBucket(this.createBucketHandler.bind(this))
})
})
})
}
static open (target, appName, callback) {
let opener
const escape = function (s) {
return s.replace(/"/g, '\\"')
}
if (typeof (appName) === 'function') {
callback = appName
appName = null
}
switch (process.platform) {
case 'darwin': {
opener = appName ? `open -a "${escape(appName)}"` : `open`
break
}
case 'win32': {
opener = appName ? `start "" ${escape(appName)}"` : `start ""`
break
}
default: {
opener = appName ? escape(appName) : `xdg-open`
break
}
}
if (process.env.SUDO_USER) {
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener
}
return exec(`${opener} "${escape(target)}"`, callback)
}
}

View File

@@ -0,0 +1,288 @@
'use strict'
const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy')
const querystring = require('querystring');
const http = require('http')
const fs = require('fs')
const url = require('url')
const exec = require('child_process').exec
const tryEach = require('async/tryEach')
const path = require('path')
const os = require('os')
const needle = require('needle')
const chalk = require('chalk')
const cst = require('../../../../constants.js')
const promptly = require('promptly')
module.exports = class CliStrategy extends AuthStrategy {
// the client will try to call this but we handle this part ourselves
retrieveTokens (km, cb) {
this.authenticated = false
this.callback = cb
this.km = km
this.BASE_URI = 'https://id.keymetrics.io';
}
// so the cli know if we need to tell user to login/register
isAuthenticated () {
return new Promise((resolve, reject) => {
if (this.authenticated) return resolve(true)
let tokensPath = cst.PM2_IO_ACCESS_TOKEN
fs.readFile(tokensPath, (err, tokens) => {
if (err && err.code === 'ENOENT') return resolve(false)
if (err) return reject(err)
// verify that the token is valid
try {
tokens = JSON.parse(tokens || '{}')
} catch (err) {
fs.unlinkSync(tokensPath)
return resolve(false)
}
// if the refresh tokens is here, the user could be automatically authenticated
return resolve(typeof tokens.refresh_token === 'string')
})
})
}
verifyToken (refresh) {
return this.km.auth.retrieveToken({
client_id: this.client_id,
refresh_token: refresh
})
}
// called when we are sure the user asked to be logged in
_retrieveTokens (optionalCallback) {
const km = this.km
const cb = this.callback
tryEach([
// try to find the token via the environment
(next) => {
if (!process.env.PM2_IO_TOKEN) {
return next(new Error('No token in env'))
}
this.verifyToken(process.env.PM2_IO_TOKEN)
.then((res) => {
return next(null, res.data)
}).catch(next)
},
// try to find it in the file system
(next) => {
fs.readFile(cst.PM2_IO_ACCESS_TOKEN, (err, tokens) => {
if (err) return next(err)
// verify that the token is valid
tokens = JSON.parse(tokens || '{}')
if (new Date(tokens.expire_at) > new Date(new Date().toISOString())) {
return next(null, tokens)
}
this.verifyToken(tokens.refresh_token)
.then((res) => {
return next(null, res.data)
}).catch(next)
})
},
// otherwise make the whole flow
(next) => {
return this.authenticate((err, data) => {
if (err instanceof Error) return next(err)
// verify that the token is valid
this.verifyToken(data.refresh_token)
.then((res) => {
return next(null, res.data)
}).catch(next)
})
}
], (err, result) => {
// if present run the optional callback
if (typeof optionalCallback === 'function') {
optionalCallback(err, result)
}
if (result.refresh_token) {
this.authenticated = true
let file = cst.PM2_IO_ACCESS_TOKEN
fs.writeFile(file, JSON.stringify(result), () => {
return cb(err, result)
})
} else {
return cb(err, result)
}
})
}
authenticate (cb) {
console.log(`${cst.PM2_IO_MSG} Using non-browser authentication.`)
promptly.confirm(`${cst.PM2_IO_MSG} Do you have a pm2.io account? (y/n)`, (err, answer) => {
// Either login or register
return answer === true ? this.login(cb) : this.register(cb)
})
}
login (cb) {
let retry = () => {
promptly.prompt(`${cst.PM2_IO_MSG} Your username or email: `, (err, username) => {
if (err) return retry();
promptly.password(`${cst.PM2_IO_MSG} Your password: `, { replace : '*' }, (err, password) => {
if (err) return retry();
console.log(`${cst.PM2_IO_MSG} Authenticating ...`)
this._loginUser({
username: username,
password: password
}, (err, data) => {
if (err) {
console.error(`${cst.PM2_IO_MSG_ERR} Failed to authenticate: ${err.message}`)
return retry()
}
return cb(null, data)
})
})
})
}
retry()
}
register (cb) {
console.log(`${cst.PM2_IO_MSG} No problem ! We just need few informations to create your account`)
var retry = () => {
promptly.prompt(`${cst.PM2_IO_MSG} Please choose an username :`, {
validator : this._validateUsername,
retry : true
}, (err, username) => {
promptly.prompt(`${cst.PM2_IO_MSG} Please choose an email :`, {
validator : this._validateEmail,
retry : true
},(err, email) => {
promptly.password(`${cst.PM2_IO_MSG} Please choose a password :`, { replace : '*' }, (err, password) => {
promptly.confirm(`${cst.PM2_IO_MSG} Do you accept the terms and privacy policy (https://pm2.io/legals/terms_conditions.pdf) ? (y/n)`, (err, answer) => {
if (err) {
console.error(chalk.bold.red(err));
return retry()
} else if (answer === false) {
console.error(`${cst.PM2_IO_MSG_ERR} You must accept the terms and privacy policy to contiue.`)
return retry()
}
this._registerUser({
email : email,
password : password,
username : username
}, (err, data) => {
console.log('\n')
if (err) {
console.error(`${cst.PM2_IO_MSG_ERR} Unexpect error: ${err.message}`)
console.error(`${cst.PM2_IO_MSG_ERR} You can also contact us to get help: contact@pm2.io`)
return process.exit(1)
}
return cb(undefined, data)
})
})
})
})
})
}
retry()
}
/**
* Register function
* @param opts.username
* @param opts.password
* @param opts.email
*/
_registerUser (opts, cb) {
const data = Object.assign(opts, {
password_confirmation: opts.password,
accept_terms: true
})
needle.post(this.BASE_URI + '/api/oauth/register', data, {
json: true,
headers: {
'X-Register-Provider': 'pm2-register',
'x-client-id': this.client_id
}
}, function (err, res, body) {
if (err) return cb(err)
if (body.email && body.email.message) return cb(new Error(body.email.message))
if (body.username && body.username.message) return cb(new Error(body.username.message))
if (!body.access_token) return cb(new Error(body.msg))
return cb(null, {
refresh_token : body.refresh_token.token,
access_token : body.access_token.token
})
});
}
_loginUser (user_info, cb) {
const URL_AUTH = '/api/oauth/authorize?response_type=token&scope=all&client_id=' +
this.client_id + '&redirect_uri=http://localhost:43532';
needle.get(this.BASE_URI + URL_AUTH, (err, res) => {
if (err) return cb(err);
var cookie = res.cookies;
needle.post(this.BASE_URI + '/api/oauth/login', user_info, {
cookies : cookie
}, (err, resp, body) => {
if (err) return cb(err)
if (resp.statusCode != 200) return cb('Wrong credentials')
var location = resp.headers['x-redirect']
needle.get(this.BASE_URI + location, {
cookies : cookie
}, (err, res) => {
if (err) return cb(err);
var refresh_token = querystring.parse(url.parse(res.headers.location).query).access_token;
needle.post(this.BASE_URI + '/api/oauth/token', {
client_id : this.client_id,
grant_type : 'refresh_token',
refresh_token : refresh_token,
scope : 'all'
}, (err, res, body) => {
if (err) return cb(err)
return cb(null, body)
})
})
})
})
}
_validateEmail (email) {
var re = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
if (re.test(email) == false)
throw new Error('Not an email');
return email;
}
_validateUsername (value) {
if (value.length < 6) {
throw new Error('Min length of 6');
}
return value;
};
deleteTokens (km) {
return new Promise((resolve, reject) => {
// revoke the refreshToken
km.auth.revoke()
.then(res => {
// remove the token from the filesystem
let file = cst.PM2_IO_ACCESS_TOKEN
fs.unlinkSync(file)
return resolve(res)
}).catch(reject)
})
}
}

View File

@@ -0,0 +1,187 @@
'use strict'
const cst = require('../../../../constants.js');
const AuthStrategy = require('@pm2/js-api/src/auth_strategies/strategy')
const http = require('http')
const fs = require('fs')
const url = require('url')
const exec = require('child_process').exec
const tryEach = require('async/tryEach');
module.exports = class WebStrategy extends AuthStrategy {
// the client will try to call this but we handle this part ourselves
retrieveTokens (km, cb) {
this.authenticated = false
this.callback = cb
this.km = km
}
// so the cli know if we need to tell user to login/register
isAuthenticated () {
return new Promise((resolve, reject) => {
if (this.authenticated) return resolve(true)
let tokensPath = cst.PM2_IO_ACCESS_TOKEN
fs.readFile(tokensPath, (err, tokens) => {
if (err && err.code === 'ENOENT') return resolve(false)
if (err) return reject(err)
// verify that the token is valid
try {
tokens = JSON.parse(tokens || '{}')
} catch (err) {
fs.unlinkSync(tokensPath)
return resolve(false)
}
// if the refresh tokens is here, the user could be automatically authenticated
return resolve(typeof tokens.refresh_token === 'string')
})
})
}
// called when we are sure the user asked to be logged in
_retrieveTokens (optionalCallback) {
const km = this.km
const cb = this.callback
let verifyToken = (refresh) => {
return km.auth.retrieveToken({
client_id: this.client_id,
refresh_token: refresh
})
}
tryEach([
// try to find the token via the environment
(next) => {
if (!process.env.PM2_IO_TOKEN) {
return next(new Error('No token in env'))
}
verifyToken(process.env.PM2_IO_TOKEN)
.then((res) => {
return next(null, res.data)
}).catch(next)
},
// try to find it in the file system
(next) => {
fs.readFile(cst.PM2_IO_ACCESS_TOKEN, (err, tokens) => {
if (err) return next(err)
// verify that the token is valid
tokens = JSON.parse(tokens || '{}')
if (new Date(tokens.expire_at) > new Date(new Date().toISOString())) {
return next(null, tokens)
}
verifyToken(tokens.refresh_token)
.then((res) => {
return next(null, res.data)
}).catch(next)
})
},
// otherwise make the whole flow
(next) => {
return this.loginViaWeb((data) => {
// verify that the token is valid
verifyToken(data.access_token)
.then((res) => {
return next(null, res.data)
}).catch(err => next(err))
})
}
], (err, result) => {
// if present run the optional callback
if (typeof optionalCallback === 'function') {
optionalCallback(err, result)
}
if (result.refresh_token) {
this.authenticated = true
let file = cst.PM2_IO_ACCESS_TOKEN
fs.writeFile(file, JSON.stringify(result), () => {
return cb(err, result)
})
} else {
return cb(err, result)
}
})
}
loginViaWeb (cb) {
const redirectURL = `${this.oauth_endpoint}${this.oauth_query}`
console.log(`${cst.PM2_IO_MSG} Please follow the popup or go to this URL :`, '\n', ' ', redirectURL)
let shutdown = false
let server = http.createServer((req, res) => {
// only handle one request
if (shutdown === true) return res.end()
shutdown = true
let query = url.parse(req.url, true).query
res.write(`
<head>
<script>
</script>
</head>
<body>
<h2 style="text-align: center">
You can go back to your terminal now :)
</h2>
</body>`)
res.end()
server.close()
return cb(query)
})
server.listen(43532, () => {
this.open(redirectURL)
})
}
deleteTokens (km) {
return new Promise((resolve, reject) => {
// revoke the refreshToken
km.auth.revoke()
.then(res => {
// remove the token from the filesystem
let file = cst.PM2_IO_ACCESS_TOKEN
fs.unlinkSync(file)
return resolve(res)
}).catch(reject)
})
}
open (target, appName, callback) {
let opener
const escape = function (s) {
return s.replace(/"/g, '\\"')
}
if (typeof (appName) === 'function') {
callback = appName
appName = null
}
switch (process.platform) {
case 'darwin': {
opener = appName ? `open -a "${escape(appName)}"` : `open`
break
}
case 'win32': {
opener = appName ? `start "" ${escape(appName)}"` : `start ""`
break
}
default: {
opener = appName ? escape(appName) : `xdg-open`
break
}
}
if (process.env.SUDO_USER) {
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener
}
return exec(`${opener} "${escape(target)}"`, callback)
}
}

View File

@@ -0,0 +1,97 @@
var cst = require('../../../constants.js');
var Common = require('../../Common.js');
const chalk = require('chalk');
const forEach = require('async/forEach');
const open = require('../../tools/open.js');
const Modules = require('../Modules');
function processesAreAlreadyMonitored(CLI, cb) {
CLI.Client.executeRemote('getMonitorData', {}, function(err, list) {
if (err) return cb(false);
var l = list.filter(l => l.pm2_env.km_link == true)
var l2 = list.filter(l => l.name == 'pm2-server-monit')
return cb(l.length > 0 && l2.length > 0 ? true : false)
})
}
module.exports = function(CLI) {
CLI.prototype.openDashboard = function() {
if (!this.gl_interact_infos) {
Common.printError(chalk.bold.white('Agent if offline, type `$ pm2 plus` to log in'));
return this.exitCli(cst.ERROR_EXIT);
}
var uri = `https://app.pm2.io/#/r/${this.gl_interact_infos.public_key}`
console.log(cst.PM2_IO_MSG + ` Opening ${uri}`)
open(uri);
setTimeout(_ => {
this.exitCli();
}, 200);
};
CLI.prototype.clearSetup = function (opts, cb) {
const modules = ['event-loop-inspector']
this.gl_is_km_linked = false
forEach(modules, (_module, next) => {
Modules.uninstall(this, _module, () => {
next()
});
}, (err) => {
this.reload('all', () => {
return cb()
})
})
}
/**
* Install required package and enable flags for current running processes
*/
CLI.prototype.minimumSetup = function (opts, cb) {
var self = this;
this.gl_is_km_linked = true
function install(cb) {
var modules = []
if (opts.type === 'enterprise' || opts.type === 'plus') {
modules = ['pm2-logrotate', 'pm2-server-monit']
if (opts.type === 'enterprise') {
modules.push('deep-metrics')
}
}
forEach(modules, (_module, next) => {
Modules.install(self, _module, {}, () => {
next()
});
}, (err) => {
self.reload('all', () => {
return cb()
})
})
}
processesAreAlreadyMonitored(self, (already_monitored) => {
if (already_monitored) {
console.log(cst.PM2_IO_MSG + ` PM2 ${opts.type || ''} bundle already installed`);
return cb()
}
if (opts.installAll)
return install(cb)
// promptly.confirm(chalk.bold('Install all pm2 plus dependencies ? (y/n)'), (err, answer) => {
// if (!err && answer === true)
return install(cb)
// self.reload('all', () => {
// return cb()
// })
// });
})
}
}

View File

@@ -0,0 +1,126 @@
var cst = require('../../../constants.js');
var Common = require('../../Common.js');
var chalk = require('chalk');
var fs = require('fs');
var KMDaemon = require('@pm2/agent/src/InteractorClient');
var pkg = require('../../../package.json')
module.exports = function(CLI) {
CLI.prototype.linkManagement = function(cmd, public_key, machine, opts, cb) {
var that = this;
// pm2 link stop || kill
if (cmd == 'stop' || cmd == 'kill') {
that.gl_is_km_linked = false
console.log(cst.PM2_IO_MSG + ' Stopping agent...');
return that.killAgent(function(err) {
if (err) {
Common.printError(err);
return process.exit(cst.ERROR_EXIT);
}
console.log(cst.PM2_IO_MSG + ' Stopped');
that.reload('all', () => {
return process.exit(cst.SUCCESS_EXIT);
})
});
}
// pm2 link info
if (cmd == 'info') {
console.log(cst.PM2_IO_MSG + ' Getting agent information...');
that.agentInfos(function(err, infos) {
if (err) {
console.error(cst.PM2_IO_MSG_ERR + ' ' + err.message);
return that.exitCli(cst.ERROR_EXIT);
}
console.log(infos);
return that.exitCli(cst.SUCCESS_EXIT);
});
return false;
}
// pm2 link delete
if (cmd == 'delete') {
that.gl_is_km_linked = false
console.log(cst.PM2_IO_MSG + ' Permanently disable agent...');
that.killAgent(function(err) {
try {
fs.unlinkSync(cst.INTERACTION_CONF);
} catch(e) {
console.log(cst.PM2_IO_MSG + ' No interaction config file found');
return process.exit(cst.SUCCESS_EXIT);
}
console.log(cst.PM2_IO_MSG + ' Agent interaction ended');
if (!cb)
return process.exit(cst.SUCCESS_EXIT);
return cb()
});
return false;
}
if (cmd && !public_key) {
console.error(cst.PM2_IO_MSG + ' Command [%s] unknown or missing public key', cmd);
return process.exit(cst.ERROR_EXIT);
}
// pm2 link xxx yyy
var infos;
if (!cmd) {
infos = null;
}
else
infos = {
public_key : public_key,
secret_key : cmd,
machine_name : machine,
info_node : opts.infoNode || null,
pm2_version: pkg.version
}
that.link(infos, cb)
};
CLI.prototype.link = function(infos, cb) {
var that = this;
process.env.WS_JSON_PATCH = true
KMDaemon.launchAndInteract(cst, infos, function(err, dt) {
if (err) {
Common.printError(cst.PM2_IO_MSG + ' Run `$ pm2 plus` to connect')
return that.exitCli(cst.ERROR_EXIT);
}
console.log(chalk.bold.green('[+] PM2+ activated!'))
if (!cb) {
return that.exitCli(cst.SUCCESS_EXIT);
}
return cb(null, dt)
});
};
CLI.prototype.agentInfos = function(cb) {
KMDaemon.getInteractInfo(this._conf, function(err, data) {
if (err)
return cb(Common.retErr(err));
return cb(null, data);
});
};
CLI.prototype.killAgent = function(cb) {
var that = this;
KMDaemon.killInteractorDaemon(that._conf, function(err) {
if (err)
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.SUCCESS_EXIT);
return cb ? cb(null) : that.exitCli(cst.SUCCESS_EXIT);
});
};
CLI.prototype.unlink = function(cb) {
this.linkManagement('delete', cb);
};
};

View File

@@ -0,0 +1,16 @@
██████╗ ███╗ ███╗██████╗ ██╗ ██╗ ██████╗
██╔══██╗████╗ ████║╚════██╗ ██║ ██╔╝██╔═══██╗
██████╔╝██╔████╔██║ █████╔╝ ██║ ██╔╝ ██║ ██║
██╔═══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔╝ ██║ ██║
██║ ██║ ╚═╝ ██║███████╗ ██║██╔╝ ╚██████╔╝
╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝╚═╝ ╚═════╝
https://pm2.io/
Harden your Node.js Production Environment
- Real-time Monitoring Web Interface
- Pro Active Alerting System
- Production Profiling for Memory and CPU
- PM2 Runtime High Availability Fallback

View File

@@ -0,0 +1,26 @@
-------------
██████╗ ███╗ ███╗██████╗ ██╗ ██╗ ██████╗
██╔══██╗████╗ ████║╚════██╗ ██║ ██╔╝██╔═══██╗
██████╔╝██╔████╔██║ █████╔╝ ██║ ██╔╝ ██║ ██║
██╔═══╝ ██║╚██╔╝██║██╔═══╝ ██║ ██╔╝ ██║ ██║
██║ ██║ ╚═╝ ██║███████╗ ██║██╔╝ ╚██████╔╝
╚═╝ ╚═╝ ╚═╝╚══════╝ ╚═╝╚═╝ ╚═════╝
https://pm2.io/
Harden your Node.js Production Environment
- Real-time Monitoring Web Interface
- Pro Active Alerting System
- Production Profiling for Memory and CPU
- PM2 Runtime High Availability Fallback
Start using it by typing:
$ pm2 plus
-------------

View File

@@ -0,0 +1,28 @@
-------------
PM2 Plus Edition
PM2 Plus is a monitoring dashboard
specialized for Node.js Apps.
Create an account:
$ pm2 plus register
Connect your local PM2 to the PM2 Plus servers:
$ pm2 plus connect
See our UI with your own realtime dashboard:
$ pm2 plus web
More details available there:
http://pm2.io/plus
-------------
Having complex or specific needs?
You can also checkout our enterprise offer at:
http://pm2.io/enterprise
-------------

View File

@@ -0,0 +1,52 @@
const fs = require('fs');
const forEachLimit = require('async/forEachLimit');
var cst = require('../../../constants.js');
var Common = require('../../Common.js');
module.exports = function(CLI) {
/**
* Monitor Selectively Processes (auto filter in interaction)
* @param String state 'monitor' or 'unmonitor'
* @param String target <pm_id|name|all>
* @param Function cb callback
*/
CLI.prototype.monitorState = function(state, target, cb) {
var that = this;
if (!target) {
Common.printError(cst.PREFIX_MSG_ERR + 'Please specify an <app_name|pm_id>');
return cb ? cb(new Error('argument missing')) : that.exitCli(cst.ERROR_EXIT);
}
function monitor (pm_id, cb) {
// State can be monitor or unmonitor
that.Client.executeRemote(state, pm_id, cb);
}
if (target === 'all') {
that.Client.getAllProcessId(function (err, procs) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
forEachLimit(procs, 1, monitor, function (err, res) {
return typeof cb === 'function' ? cb(err, res) : that.speedList();
});
});
} else if (!Number.isInteger(parseInt(target))) {
this.Client.getProcessIdByName(target, true, function (err, procs) {
if (err) {
Common.printError(err);
return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
}
forEachLimit(procs, 1, monitor, function (err, res) {
return typeof cb === 'function' ? cb(err, res) : that.speedList();
});
});
} else {
monitor(parseInt(target), function (err, res) {
return typeof cb === 'function' ? cb(err, res) : that.speedList();
});
}
};
}

375
api.hyungi.net/node_modules/pm2/lib/API/schema.json generated vendored Normal file
View File

@@ -0,0 +1,375 @@
{
"script": {
"type": "string",
"require": true,
"alias" : "exec",
"docDescription": "Path of the script to launch, required field"
},
"name": {
"type": "string",
"docDefault": "Script filename without the extension (app for app.js)",
"docDescription": "Process name in the process list"
},
"name_prefix": {
"type": "string"
},
"filter_env": {
"type": [
"boolean",
"array",
"string"
],
"docDefault": false,
"docDescription": "Enable filtering global environments"
},
"namespace": {
"type": "string",
"docDefault": "default",
"docDescription": "Process namespace"
},
"install_url": {
"type": "string"
},
"cwd": {
"type": "string",
"docDefault": "CWD of the current environment (from your shell)",
"docDescription": "Current working directory to start the process with"
},
"args": {
"type": [
"array",
"string"
],
"docDescription": "Arguments to pass to the script"
},
"exec_interpreter": {
"type": "string",
"alias": "interpreter",
"docDefault": "node",
"docDescription": "Interpreter absolute path"
},
"node_args": {
"type": [
"array",
"string"
],
"alias": ["interpreterArgs", "interpreter_args"],
"docDescription": "Arguments to pass to the interpreter"
},
"out_file": {
"type": "string",
"alias": ["out", "output", "out_log"],
"docDefault": "~/.pm2/logs/<app_name>-out.log",
"docDescription": "File path for stdout (each line is appended to this file)"
},
"error_file": {
"type": "string",
"alias": ["error", "err", "err_file", "err_log"],
"docDefault": "~/.pm2/logs/<app_name>-error.err",
"docDescription": "File path for stderr (each line is appended to this file)"
},
"log_file": {
"type": [
"boolean",
"string"
],
"alias": "log",
"docDefault": "/dev/null",
"docDescription": "File path for combined stdout and stderr (each line is appended to this file)"
},
"disable_logs": {
"type": "boolean",
"docDefault": false,
"docDescription": "Disable all logs storage"
},
"log_type": {
"type": "string",
"docDescription": "Define a specific log output type, possible value: json"
},
"log_date_format": {
"type": "string",
"docDescription": "Format for log timestamps in day.js format (eg YYYY-MM-DD HH:mm Z)"
},
"time": {
"type": "boolean"
},
"env": {
"type": [
"object",
"string"
],
"docDescription": "Specify environment variables to be injected"
},
"^env_\\S*$": {
"type": [
"object",
"string"
],
"docDescription": "Specify environment variables to be injected when using --env <env_name>"
},
"max_memory_restart": {
"type": [
"string",
"number"
],
"regex": "^\\d+(G|M|K)?$",
"ext_type": "sbyte",
"desc": "it should be a NUMBER - byte, \"[NUMBER]G\"(Gigabyte), \"[NUMBER]M\"(Megabyte) or \"[NUMBER]K\"(Kilobyte)",
"docDescription": "Restart the app if an amount of memory is exceeded (format: /[0-9](K&#124;M&#124;G)?/ K for KB, 'M' for MB, 'G' for GB, default to B)"
},
"pid_file": {
"type": "string",
"alias": "pid",
"docDefault": "~/.pm2/pids/app_name-id.pid",
"docDescription": "File path where the pid of the started process is written by pm2"
},
"restart_delay": {
"type" : "number",
"docDefault": 0,
"docDescription": "Time in ms to wait before restarting a crashing app"
},
"exp_backoff_restart_delay": {
"type": "number",
"docDefault": 0,
"docDescription": "Restart Time in ms to wait before restarting a crashing app"
},
"source_map_support": {
"type": "boolean",
"docDefault": true,
"docDescription": "Enable or disable the source map support"
},
"disable_source_map_support": {
"type": "boolean",
"docDefault": false,
"docDescription": "Enable or disable the source map support"
},
"wait_ready": {
"type": "boolean",
"docDefault": false,
"docDescription": "Make the process wait for a process.send('ready')"
},
"instances": {
"type": "number",
"docDefault": 1,
"docDescription": "Number of instances to be started in cluster mode"
},
"kill_timeout": {
"type": "number",
"docDefault": 1600,
"docDescription": "Time in ms before sending the final SIGKILL signal after SIGINT"
},
"shutdown_with_message": {
"type": "boolean",
"docDefault": false,
"docDescription": "Shutdown an application with process.send('shutdown') instead of process.kill(pid, SIGINT)"
},
"listen_timeout": {
"type": "number",
"docDescription": "Time in ms before forcing a reload if app is still not listening/has still note sent ready"
},
"cron_restart": {
"type": [
"string",
"number"
],
"alias": "cron",
"docDescription": "A cron pattern to restart your app"
},
"merge_logs": {
"type": "boolean",
"alias" : "combine_logs",
"docDefault": false,
"docDescription": "In cluster mode, merge each type of logs into a single file (instead of having one for each cluster)"
},
"vizion": {
"type": "boolean",
"default" : true,
"docDefault" : "True",
"docDescription": "Enable or disable the versioning metadatas (vizion library)"
},
"autostart": {
"type": "boolean",
"default": true,
"docDefault": "True",
"docDescription": "Enable or disable auto start when adding process"
},
"autorestart": {
"type": "boolean",
"default": true,
"docDefault": "True",
"docDescription": "Enable or disable auto restart after process failure"
},
"stop_exit_codes": {
"type": [
"array",
"number"
],
"docDescription": "List of exit codes that should allow the process to stop (skip autorestart)."
},
"watch_delay": {
"type": "number",
"docDefault": "True",
"docDescription": "Restart delay on file change detected"
},
"watch": {
"type": [
"boolean",
"array",
"string"
],
"docDefault": false,
"docDescription": "Enable or disable the watch mode"
},
"ignore_watch": {
"type": [
"array",
"string"
],
"docDescription": "List of paths to ignore (regex)"
},
"watch_options": {
"type": "object",
"docDescription": "Object that will be used as an options with chokidar (refer to chokidar documentation)"
},
"min_uptime": {
"type": [
"number",
"string"
],
"regex": "^\\d+(h|m|s)?$",
"desc": "it should be a NUMBER - milliseconds, \"[NUMBER]h\"(hours), \"[NUMBER]m\"(minutes) or \"[NUMBER]s\"(seconds)",
"min": 100,
"ext_type": "stime",
"docDefault": 1000,
"docDescription": "Minimum uptime of the app to be considered started (format is /[0-9]+(h&#124;m&#124;s)?/, for hours, minutes, seconds, docDefault to ms)"
},
"max_restarts": {
"type": "number",
"min": 0,
"docDefault": 16,
"docDescription": "Number of times a script is restarted when it exits in less than min_uptime"
},
"execute_command": {
"type": "boolean"
},
"exec_mode": {
"type": "string",
"regex": "^(cluster|fork)(_mode)?$",
"desc": "it should be \"cluster\"(\"cluster_mode\") or \"fork\"(\"fork_mode\") only",
"docDefault": "fork",
"docDescription": "Set the execution mode, possible values: fork&#124;cluster"
},
"force": {
"type": "boolean",
"docDefault": false,
"docDescription": "Start a script even if it is already running (only the script path is considered)"
},
"append_env_to_name": {
"type": "boolean",
"docDefault": false,
"docDescription": "Append the environment name to the app name"
},
"post_update": {
"type": "array",
"docDescription": "List of commands executed after a pull/upgrade operation performed from Keymetrics dashboard"
},
"trace": {
"type": [
"boolean"
],
"docDefault": false,
"docDescription": "Enable or disable the transaction tracing"
},
"disable_trace": {
"type": [
"boolean"
],
"docDefault": true,
"docDescription": "Enable or disable the transaction tracing"
},
"v8": {
"type": [
"boolean"
]
},
"event_loop_inspector": {
"type": [
"boolean"
]
},
"deep_monitoring": {
"type": [
"boolean"
]
},
"increment_var": {
"type": "string",
"docDescription": "Specify the name of an environment variable to inject which increments for each cluster"
},
"instance_var": {
"type": "string",
"default": "NODE_APP_INSTANCE",
"docDefault": "NODE_APP_INSTANCE",
"docDescription": "Rename the NODE_APP_INSTANCE environment variable"
},
"pmx": {
"type": ["boolean", "string"],
"default": true,
"docDefault": "True",
"docDescription": "Enable or disable pmx wrapping"
},
"automation": {
"type": "boolean",
"default": true,
"docDefault": "True",
"docDescription": "Enable or disable pmx wrapping"
},
"treekill": {
"type": "boolean",
"default": true,
"docDefault": "True",
"docDescription": "Only kill the main process, not detached children"
},
"port": {
"type": "number",
"docDescription": "Shortcut to inject a PORT environment variable"
},
"username" : {
"type": "string",
"docDescription": "Current user that started the process"
},
"uid": {
"type" : [
"number",
"string"
],
"alias": "user",
"docDefault": "Current user uid",
"docDescription": "Set user id"
},
"gid": {
"type" : [
"number",
"string"
],
"docDefault": "Current user gid",
"docDescription": "Set group id"
},
"windowsHide": {
"type": "boolean",
"docDefault": "True",
"docDescription": "Enable or disable the Windows popup when starting an app",
"default": true
},
"kill_retry_time": {
"type": "number",
"default" : 100
},
"write": {
"type": "boolean"
},
"io": {
"type": "object",
"docDescription": "Specify apm values and configuration"
}
}

779
api.hyungi.net/node_modules/pm2/lib/Client.js generated vendored Normal file
View File

@@ -0,0 +1,779 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var debug = require('debug')('pm2:client');
var Common = require('./Common.js');
var KMDaemon = require('@pm2/agent/src/InteractorClient');
var rpc = require('pm2-axon-rpc');
var forEach = require('async/forEach');
var axon = require('pm2-axon');
var util = require('util');
var fs = require('fs');
var path = require('path');
var pkg = require('../package.json');
var which = require('./tools/which.js');
function noop() {}
var Client = module.exports = function(opts) {
if (!opts) opts = {};
if (!opts.conf)
this.conf = require('../constants.js');
else {
this.conf = opts.conf;
}
this.daemon_mode = typeof(opts.daemon_mode) === 'undefined' ? true : opts.daemon_mode;
this.pm2_home = this.conf.PM2_ROOT_PATH;
this.secret_key = opts.secret_key;
this.public_key = opts.public_key;
this.machine_name = opts.machine_name;
// Create all folders and files needed
// Client depends to that to interact with PM2 properly
this.initFileStructure(this.conf);
debug('Using RPC file %s', this.conf.DAEMON_RPC_PORT);
debug('Using PUB file %s', this.conf.DAEMON_PUB_PORT);
this.rpc_socket_file = this.conf.DAEMON_RPC_PORT;
this.pub_socket_file = this.conf.DAEMON_PUB_PORT;
};
// @breaking change (noDaemonMode has been drop)
// @todo ret err
Client.prototype.start = function(cb) {
var that = this;
this.pingDaemon(function(daemonAlive) {
if (daemonAlive === true)
return that.launchRPC(function(err, meta) {
return cb(null, {
daemon_mode : that.conf.daemon_mode,
new_pm2_instance : false,
rpc_socket_file : that.rpc_socket_file,
pub_socket_file : that.pub_socket_file,
pm2_home : that.pm2_home
});
});
/**
* No Daemon mode
*/
if (that.daemon_mode === false) {
var Daemon = require('./Daemon.js');
var daemon = new Daemon({
pub_socket_file : that.conf.DAEMON_PUB_PORT,
rpc_socket_file : that.conf.DAEMON_RPC_PORT,
pid_file : that.conf.PM2_PID_FILE_PATH,
ignore_signals : true
});
console.log('Launching in no daemon mode');
daemon.innerStart(function() {
KMDaemon.launchAndInteract(that.conf, {
machine_name : that.machine_name,
public_key : that.public_key,
secret_key : that.secret_key,
pm2_version : pkg.version
}, function(err, data, interactor_proc) {
that.interactor_process = interactor_proc;
});
that.launchRPC(function(err, meta) {
return cb(null, {
daemon_mode : that.conf.daemon_mode,
new_pm2_instance : true,
rpc_socket_file : that.rpc_socket_file,
pub_socket_file : that.pub_socket_file,
pm2_home : that.pm2_home
});
});
});
return false;
}
/**
* Daemon mode
*/
that.launchDaemon(function(err, child) {
if (err) {
Common.printError(err);
return cb ? cb(err) : process.exit(that.conf.ERROR_EXIT);
}
if (!process.env.PM2_DISCRETE_MODE)
Common.printOut(that.conf.PREFIX_MSG + 'PM2 Successfully daemonized');
that.launchRPC(function(err, meta) {
return cb(null, {
daemon_mode : that.conf.daemon_mode,
new_pm2_instance : true,
rpc_socket_file : that.rpc_socket_file,
pub_socket_file : that.pub_socket_file,
pm2_home : that.pm2_home
});
});
});
});
};
// Init file structure of pm2_home
// This includes
// - pm2 pid and log path
// - rpc and pub socket for command execution
Client.prototype.initFileStructure = function (opts) {
if (!fs.existsSync(opts.DEFAULT_LOG_PATH)) {
try {
require('mkdirp').sync(opts.DEFAULT_LOG_PATH);
} catch (e) {
console.error(e.stack || e);
}
}
if (!fs.existsSync(opts.DEFAULT_PID_PATH)) {
try {
require('mkdirp').sync(opts.DEFAULT_PID_PATH);
} catch (e) {
console.error(e.stack || e);
}
}
if (!fs.existsSync(opts.PM2_MODULE_CONF_FILE)) {
try {
fs.writeFileSync(opts.PM2_MODULE_CONF_FILE, "{}");
} catch (e) {
console.error(e.stack || e);
}
}
if (!fs.existsSync(opts.DEFAULT_MODULE_PATH)) {
try {
require('mkdirp').sync(opts.DEFAULT_MODULE_PATH);
} catch (e) {
console.error(e.stack || e);
}
}
if (process.env.PM2_DISCRETE_MODE) {
try {
fs.writeFileSync(path.join(opts.PM2_HOME, 'touch'), Date.now().toString());
} catch(e) {
debug(e.stack || e);
}
}
if (!process.env.PM2_PROGRAMMATIC && !fs.existsSync(path.join(opts.PM2_HOME, 'touch'))) {
var vCheck = require('./VersionCheck.js')
vCheck({
state: 'install',
version: pkg.version
})
var dt = fs.readFileSync(path.join(__dirname, opts.PM2_BANNER));
console.log(dt.toString());
try {
fs.writeFileSync(path.join(opts.PM2_HOME, 'touch'), Date.now().toString());
} catch(e) {
debug(e.stack || e);
}
}
};
Client.prototype.close = function(cb) {
var that = this;
forEach([
that.disconnectRPC.bind(that),
that.disconnectBus.bind(that)
], function(fn, next) {
fn(next)
}, cb);
};
/**
* Launch the Daemon by forking this same file
* The method Client.remoteWrapper will be called
*
* @method launchDaemon
* @param {Object} opts
* @param {Object} [opts.interactor=true] allow to disable interaction on launch
*/
Client.prototype.launchDaemon = function(opts, cb) {
if (typeof(opts) == 'function') {
cb = opts;
opts = {
interactor : true
};
}
var that = this
var ClientJS = path.resolve(path.dirname(module.filename), 'Daemon.js');
var node_args = [];
var out, err;
// if (process.env.TRAVIS) {
// // Redirect PM2 internal err and out to STDERR STDOUT when running with Travis
// out = 1;
// err = 2;
// }
// else {
out = fs.openSync(that.conf.PM2_LOG_FILE_PATH, 'a'),
err = fs.openSync(that.conf.PM2_LOG_FILE_PATH, 'a');
//}
if (this.conf.LOW_MEMORY_ENVIRONMENT) {
var os = require('os');
node_args.push('--gc-global'); // Does full GC (smaller memory footprint)
node_args.push('--max-old-space-size=' + Math.floor(os.totalmem() / 1024 / 1024));
}
// Node.js tuning for better performance
//node_args.push('--expose-gc'); // Allows manual GC in the code
/**
* Add node [arguments] depending on PM2_NODE_OPTIONS env variable
*/
if (process.env.PM2_NODE_OPTIONS)
node_args = node_args.concat(process.env.PM2_NODE_OPTIONS.split(' '));
node_args.push(ClientJS);
if (!process.env.PM2_DISCRETE_MODE)
Common.printOut(that.conf.PREFIX_MSG + 'Spawning PM2 daemon with pm2_home=' + this.pm2_home);
var interpreter = 'node';
if (which('node') == null)
interpreter = process.execPath;
var child = require('child_process').spawn(interpreter, node_args, {
detached : true,
cwd : that.conf.cwd || process.cwd(),
windowsHide: true,
env : Object.assign({
'SILENT' : that.conf.DEBUG ? !that.conf.DEBUG : true,
'PM2_HOME' : that.pm2_home
}, process.env),
stdio : ['ipc', out, err]
});
function onError(e) {
console.error(e.message || e);
return cb ? cb(e.message || e) : false;
}
child.once('error', onError);
child.unref();
child.once('message', function(msg) {
debug('PM2 daemon launched with return message: ', msg);
child.removeListener('error', onError);
child.disconnect();
if (opts && opts.interactor == false)
return cb(null, child);
if (process.env.PM2_NO_INTERACTION == 'true')
return cb(null, child);
/**
* Here the Keymetrics agent is launched automaticcaly if
* it has been already configured before (via pm2 link)
*/
KMDaemon.launchAndInteract(that.conf, {
machine_name : that.machine_name,
public_key : that.public_key,
secret_key : that.secret_key,
pm2_version : pkg.version
}, function(err, data, interactor_proc) {
that.interactor_process = interactor_proc;
return cb(null, child);
});
});
};
/**
* Ping the daemon to know if it alive or not
* @api public
* @method pingDaemon
* @param {} cb
* @return
*/
Client.prototype.pingDaemon = function pingDaemon(cb) {
var req = axon.socket('req');
var client = new rpc.Client(req);
var that = this;
debug('[PING PM2] Trying to connect to server');
client.sock.once('reconnect attempt', function() {
client.sock.close();
debug('Daemon not launched');
process.nextTick(function() {
return cb(false);
});
});
client.sock.once('error', function(e) {
if (e.code === 'EACCES') {
fs.stat(that.conf.DAEMON_RPC_PORT, function(e, stats) {
if (stats.uid === 0) {
console.error(that.conf.PREFIX_MSG_ERR + 'Permission denied, to give access to current user:');
console.log('$ sudo chown ' + process.env.USER + ':' + process.env.USER + ' ' + that.conf.DAEMON_RPC_PORT + ' ' + that.conf.DAEMON_PUB_PORT);
}
else
console.error(that.conf.PREFIX_MSG_ERR + 'Permission denied, check permissions on ' + that.conf.DAEMON_RPC_PORT);
process.exit(1);
});
}
else
console.error(e.message || e);
});
client.sock.once('connect', function() {
client.sock.once('close', function() {
return cb(true);
});
client.sock.close();
debug('Daemon alive');
});
req.connect(this.rpc_socket_file);
};
/**
* Methods to interact with the Daemon via RPC
* This method wait to be connected to the Daemon
* Once he's connected it trigger the command parsing (on ./bin/pm2 file, at the end)
* @method launchRPC
* @params {function} [cb]
* @return
*/
Client.prototype.launchRPC = function launchRPC(cb) {
var self = this;
debug('Launching RPC client on socket file %s', this.rpc_socket_file);
var req = axon.socket('req');
this.client = new rpc.Client(req);
var connectHandler = function() {
self.client.sock.removeListener('error', errorHandler);
debug('RPC Connected to Daemon');
if (cb) {
setTimeout(function() {
cb(null);
}, 4);
}
};
var errorHandler = function(e) {
self.client.sock.removeListener('connect', connectHandler);
if (cb) {
return cb(e);
}
};
this.client.sock.once('connect', connectHandler);
this.client.sock.once('error', errorHandler);
this.client_sock = req.connect(this.rpc_socket_file);
};
/**
* Methods to close the RPC connection
* @callback cb
*/
Client.prototype.disconnectRPC = function disconnectRPC(cb) {
var that = this;
if (!cb) cb = noop;
if (!this.client_sock || !this.client_sock.close) {
this.client = null;
return process.nextTick(function() {
cb(new Error('SUB connection to PM2 is not launched'));
});
}
if (this.client_sock.connected === false ||
this.client_sock.closing === true) {
this.client = null;
return process.nextTick(function() {
cb(new Error('RPC already being closed'));
});
}
try {
var timer;
that.client_sock.once('close', function() {
clearTimeout(timer);
that.client = null;
debug('PM2 RPC cleanly closed');
return cb(null, { msg : 'RPC Successfully closed' });
});
timer = setTimeout(function() {
if (that.client_sock.destroy)
that.client_sock.destroy();
that.client = null;
return cb(null, { msg : 'RPC Successfully closed via timeout' });
}, 200);
that.client_sock.close();
} catch(e) {
debug('Error while disconnecting RPC PM2', e.stack || e);
return cb(e);
}
return false;
};
Client.prototype.launchBus = function launchEventSystem(cb) {
var self = this;
this.sub = axon.socket('sub-emitter');
this.sub_sock = this.sub.connect(this.pub_socket_file);
this.sub_sock.once('connect', function() {
return cb(null, self.sub, self.sub_sock);
});
};
Client.prototype.disconnectBus = function disconnectBus(cb) {
if (!cb) cb = noop;
var that = this;
if (!this.sub_sock || !this.sub_sock.close) {
that.sub = null;
return process.nextTick(function() {
cb(null, { msg : 'bus was not connected'});
});
}
if (this.sub_sock.connected === false ||
this.sub_sock.closing === true) {
that.sub = null;
return process.nextTick(function() {
cb(new Error('SUB connection is already being closed'));
});
}
try {
var timer;
that.sub_sock.once('close', function() {
that.sub = null;
clearTimeout(timer);
debug('PM2 PUB cleanly closed');
return cb();
});
timer = setTimeout(function() {
if (Client.sub_sock.destroy)
that.sub_sock.destroy();
return cb();
}, 200);
this.sub_sock.close();
} catch(e) {
return cb(e);
}
};
/**
* Description
* @method gestExposedMethods
* @param {} cb
* @return
*/
Client.prototype.getExposedMethods = function getExposedMethods(cb) {
this.client.methods(cb);
};
/**
* Description
* @method executeRemote
* @param {} method
* @param {} env
* @param {} fn
* @return
*/
Client.prototype.executeRemote = function executeRemote(method, app_conf, fn) {
var self = this;
// stop watch on stop | env is the process id
if (method.indexOf('stop') !== -1) {
this.stopWatch(method, app_conf);
}
// stop watching when process is deleted
else if (method.indexOf('delete') !== -1) {
this.stopWatch(method, app_conf);
}
// stop everything on kill
else if (method.indexOf('kill') !== -1) {
this.stopWatch('deleteAll', app_conf);
}
else if (method.indexOf('restartProcessId') !== -1 && process.argv.indexOf('--watch') > -1) {
delete app_conf.env.current_conf.watch;
this.toggleWatch(method, app_conf);
}
if (!this.client || !this.client.call) {
this.start(function(error) {
if (error) {
if (fn)
return fn(error);
console.error(error);
return process.exit(0);
}
if (self.client) {
return self.client.call(method, app_conf, fn);
}
});
return false;
}
debug('Calling daemon method pm2:%s on rpc socket:%s', method, this.rpc_socket_file);
return this.client.call(method, app_conf, fn);
};
Client.prototype.notifyGod = function(action_name, id, cb) {
this.executeRemote('notifyByProcessId', {
id : id,
action_name : action_name,
manually : true
}, function() {
debug('God notified');
return cb ? cb() : false;
});
};
Client.prototype.killDaemon = function killDaemon(fn) {
var timeout;
var that = this;
function quit() {
that.close(function() {
return fn ? fn(null, {success:true}) : false;
});
}
// under unix, we listen for signal (that is send by daemon to notify us that its shuting down)
if (process.platform !== 'win32' && process.platform !== 'win64') {
process.once('SIGQUIT', function() {
debug('Received SIGQUIT from pm2 daemon');
clearTimeout(timeout);
quit();
});
}
else {
// if under windows, try to ping the daemon to see if it still here
setTimeout(function() {
that.pingDaemon(function(alive) {
if (!alive) {
clearTimeout(timeout);
return quit();
}
});
}, 250)
}
timeout = setTimeout(function() {
quit();
}, 3000);
// Kill daemon
this.executeRemote('killMe', {pid : process.pid});
};
/**
* Description
* @method toggleWatch
* @param {String} pm2 method name
* @param {Object} application environment, should include id
* @param {Function} callback
*/
Client.prototype.toggleWatch = function toggleWatch(method, env, fn) {
debug('Calling toggleWatch');
this.client.call('toggleWatch', method, env, function() {
return fn ? fn() : false;
});
};
/**
* Description
* @method startWatch
* @param {String} pm2 method name
* @param {Object} application environment, should include id
* @param {Function} callback
*/
Client.prototype.startWatch = function restartWatch(method, env, fn) {
debug('Calling startWatch');
this.client.call('startWatch', method, env, function() {
return fn ? fn() : false;
});
};
/**
* Description
* @method stopWatch
* @param {String} pm2 method name
* @param {Object} application environment, should include id
* @param {Function} callback
*/
Client.prototype.stopWatch = function stopWatch(method, env, fn) {
debug('Calling stopWatch');
this.client.call('stopWatch', method, env, function() {
return fn ? fn() : false;
});
};
Client.prototype.getAllProcess = function(cb) {
var found_proc = [];
this.executeRemote('getMonitorData', {}, function(err, procs) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
return cb(null, procs);
});
};
Client.prototype.getAllProcessId = function(cb) {
var found_proc = [];
this.executeRemote('getMonitorData', {}, function(err, procs) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
return cb(null, procs.map(proc => proc.pm_id));
});
};
Client.prototype.getAllProcessIdWithoutModules = function(cb) {
var found_proc = [];
this.executeRemote('getMonitorData', {}, function(err, procs) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
var proc_ids = procs
.filter(proc => !proc.pm2_env.pmx_module)
.map(proc => proc.pm_id)
return cb(null, proc_ids);
});
};
Client.prototype.getProcessIdByName = function(name, force_all, cb) {
var found_proc = [];
var full_details = {};
if (typeof(cb) === 'undefined') {
cb = force_all;
force_all = false;
}
if (typeof(name) == 'number')
name = name.toString();
this.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
list.forEach(function(proc) {
if (proc.pm2_env.name == name || proc.pm2_env.pm_exec_path == path.resolve(name)) {
found_proc.push(proc.pm_id);
full_details[proc.pm_id] = proc;
}
});
return cb(null, found_proc, full_details);
});
};
Client.prototype.getProcessIdsByNamespace = function(namespace, force_all, cb) {
var found_proc = [];
var full_details = {};
if (typeof(cb) === 'undefined') {
cb = force_all;
force_all = false;
}
if (typeof(namespace) == 'number')
namespace = namespace.toString();
this.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
list.forEach(function(proc) {
if (proc.pm2_env.namespace == namespace) {
found_proc.push(proc.pm_id);
full_details[proc.pm_id] = proc;
}
});
return cb(null, found_proc, full_details);
});
};
Client.prototype.getProcessByName = function(name, cb) {
var found_proc = [];
this.executeRemote('getMonitorData', {}, function(err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
list.forEach(function(proc) {
if (proc.pm2_env.name == name ||
proc.pm2_env.pm_exec_path == path.resolve(name)) {
found_proc.push(proc);
}
});
return cb(null, found_proc);
});
};
Client.prototype.getProcessByNameOrId = function (nameOrId, cb) {
var foundProc = [];
this.executeRemote('getMonitorData', {}, function (err, list) {
if (err) {
Common.printError('Error retrieving process list: ' + err);
return cb(err);
}
list.forEach(function (proc) {
if (proc.pm2_env.name === nameOrId ||
proc.pm2_env.pm_exec_path === path.resolve(nameOrId) ||
proc.pid === parseInt(nameOrId) ||
proc.pm2_env.pm_id === parseInt(nameOrId)) {
foundProc.push(proc);
}
});
return cb(null, foundProc);
});
};

904
api.hyungi.net/node_modules/pm2/lib/Common.js generated vendored Normal file
View File

@@ -0,0 +1,904 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
/**
* Common Utilities ONLY USED IN ->CLI<-
*/
var fs = require('fs');
var path = require('path');
var os = require('os');
var util = require('util');
var chalk = require('chalk');
var fclone = require('fclone');
var semver = require('semver');
var dayjs = require('dayjs');
var execSync = require('child_process').execSync;
var isBinary = require('./tools/isbinaryfile.js');
var cst = require('../constants.js');
var extItps = require('./API/interpreter.json');
var Config = require('./tools/Config');
var pkg = require('../package.json');
var which = require('./tools/which.js');
var Common = module.exports;
function homedir() {
var env = process.env;
var home = env.HOME;
var user = env.LOGNAME || env.USER || env.LNAME || env.USERNAME;
if (process.platform === 'win32') {
return env.USERPROFILE || env.HOMEDRIVE + env.HOMEPATH || home || null;
}
if (process.platform === 'darwin') {
return home || (user ? '/Users/' + user : null);
}
if (process.platform === 'linux') {
return home || (process.getuid() === 0 ? '/root' : (user ? '/home/' + user : null));
}
return home || null;
}
function resolveHome(filepath) {
if (filepath[0] === '~') {
return path.join(homedir(), filepath.slice(1));
}
return filepath;
}
Common.determineSilentCLI = function() {
// pm2 should ignore -s --silent -v if they are after '--'
var variadicArgsDashesPos = process.argv.indexOf('--');
var s1opt = process.argv.indexOf('--silent')
var s2opt = process.argv.indexOf('-s')
if (process.env.PM2_SILENT || (variadicArgsDashesPos > -1 &&
(s1opt != -1 && s1opt < variadicArgsDashesPos) &&
(s2opt != -1 != s2opt < variadicArgsDashesPos)) ||
(variadicArgsDashesPos == -1 && (s1opt > -1 || s2opt > -1))) {
for (var key in console){
var code = key.charCodeAt(0);
if (code >= 97 && code <= 122){
console[key] = function(){};
}
}
process.env.PM2_DISCRETE_MODE = true;
}
}
Common.printVersion = function() {
var variadicArgsDashesPos = process.argv.indexOf('--');
if (process.argv.indexOf('-v') > -1 && process.argv.indexOf('-v') < variadicArgsDashesPos) {
console.log(pkg.version);
process.exit(0);
}
}
Common.lockReload = function() {
try {
var t1 = fs.readFileSync(cst.PM2_RELOAD_LOCKFILE).toString();
// Check if content and if time < 30 return locked
// Else if content detected (lock file staled), allow and rewritte
if (t1 && t1 != '') {
var diff = dayjs().diff(parseInt(t1));
if (diff < cst.RELOAD_LOCK_TIMEOUT)
return diff;
}
} catch(e) {}
try {
// Write latest timestamp
fs.writeFileSync(cst.PM2_RELOAD_LOCKFILE, dayjs().valueOf().toString());
return 0;
} catch(e) {
console.error(e.message || e);
}
};
Common.unlockReload = function() {
try {
fs.writeFileSync(cst.PM2_RELOAD_LOCKFILE, '');
} catch(e) {
console.error(e.message || e);
}
};
/**
* Resolve app paths and replace missing values with defaults.
* @method prepareAppConf
* @param app {Object}
* @param {} cwd
* @param {} outputter
* @return app
*/
Common.prepareAppConf = function(opts, app) {
/**
* Minimum validation
*/
if (!app.script)
return new Error('No script path - aborting');
var cwd = null;
if (app.cwd) {
cwd = path.resolve(app.cwd);
process.env.PWD = app.cwd;
}
if (!app.node_args) {
app.node_args = [];
}
if (app.port && app.env) {
app.env.PORT = app.port;
}
// CWD option resolving
cwd && (cwd[0] != '/') && (cwd = path.resolve(process.cwd(), cwd));
cwd = cwd || opts.cwd;
// Full path script resolution
app.pm_exec_path = path.resolve(cwd, app.script);
// If script does not exist after resolution
if (!fs.existsSync(app.pm_exec_path)) {
var ckd;
// Try resolve command available in $PATH
if ((ckd = which(app.script))) {
if (typeof(ckd) !== 'string')
ckd = ckd.toString();
app.pm_exec_path = ckd;
}
else
// Throw critical error
return new Error(`Script not found: ${app.pm_exec_path}`);
}
/**
* Auto detect .map file and enable source map support automatically
*/
if (app.disable_source_map_support != true) {
try {
fs.accessSync(app.pm_exec_path + '.map', fs.R_OK);
app.source_map_support = true;
} catch(e) {}
delete app.disable_source_map_support;
}
delete app.script;
// Set current env by first adding the process environment and then extending/replacing it
// with env specified on command-line or JSON file.
var env = {};
/**
* Do not copy internal pm2 environment variables if acting on process
* is made from a programmatic script started by PM2 or if a pm_id is present in env
*/
if (cst.PM2_PROGRAMMATIC || process.env.pm_id)
Common.safeExtend(env, process.env);
else
env = process.env;
function filterEnv (envObj) {
if (app.filter_env == true)
return {}
if (typeof app.filter_env === 'string') {
delete envObj[app.filter_env]
return envObj
}
var new_env = {};
var allowedKeys = app.filter_env.reduce((acc, current) =>
acc.filter( item => !item.includes(current)), Object.keys(envObj))
allowedKeys.forEach( key => new_env[key] = envObj[key]);
return new_env
}
app.env = [
{}, (app.filter_env && app.filter_env.length > 0) ? filterEnv(process.env) : env, app.env || {}
].reduce(function(e1, e2){
return Object.assign(e1, e2);
});
app.pm_cwd = cwd;
// Interpreter
try {
Common.sink.resolveInterpreter(app);
} catch(e) {
return e
}
// Exec mode and cluster stuff
Common.sink.determineExecMode(app);
/**
* Scary
*/
var formated_app_name = app.name.replace(/[^a-zA-Z0-9\\.\\-]/g, '-');
['log', 'out', 'error', 'pid'].forEach(function(f){
var af = app[f + '_file'], ps, ext = (f == 'pid' ? 'pid':'log'), isStd = !~['log', 'pid'].indexOf(f);
if (af) af = resolveHome(af);
if ((f == 'log' && typeof af == 'boolean' && af) || (f != 'log' && !af)) {
ps = [cst['DEFAULT_' + ext.toUpperCase() + '_PATH'], formated_app_name + (isStd ? '-' + f : '') + '.' + ext];
} else if ((f != 'log' || (f == 'log' && af)) && af !== 'NULL' && af !== '/dev/null') {
ps = [cwd, af];
var dir = path.dirname(path.resolve(cwd, af));
if (!fs.existsSync(dir)) {
Common.printError(cst.PREFIX_MSG_WARNING + 'Folder does not exist: ' + dir);
Common.printOut(cst.PREFIX_MSG + 'Creating folder: ' + dir);
try {
require('mkdirp').sync(dir);
} catch (err) {
Common.printError(cst.PREFIX_MSG_ERR + 'Could not create folder: ' + path.dirname(af));
throw new Error('Could not create folder');
}
}
}
// PM2 paths
if (af !== 'NULL' && af !== '/dev/null') {
ps && (app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = path.resolve.apply(null, ps));
} else if (path.sep === '\\') {
app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = '\\\\.\\NUL';
} else {
app['pm_' + (isStd ? f.substr(0, 3) + '_' : '') + ext + '_path'] = '/dev/null';
}
delete app[f + '_file'];
});
return app;
};
/**
* Definition of known config file extensions with their type
*/
Common.knonwConfigFileExtensions = {
'.json': 'json',
'.yml': 'yaml',
'.yaml': 'yaml',
'.config.js': 'js',
'.config.cjs': 'js',
'.config.mjs': 'mjs'
}
/**
* Check if filename is a configuration file
* @param {string} filename
* @return {mixed} null if not conf file, json or yaml if conf
*/
Common.isConfigFile = function (filename) {
if (typeof (filename) !== 'string')
return null;
for (let extension in Common.knonwConfigFileExtensions) {
if (filename.indexOf(extension) !== -1) {
return Common.knonwConfigFileExtensions[extension];
}
}
return null;
};
Common.getConfigFileCandidates = function (name) {
return Object.keys(Common.knonwConfigFileExtensions).map((extension) => name + extension);
}
/**
* Parses a config file like ecosystem.config.js. Supported formats: JS, JSON, JSON5, YAML.
* @param {string} confString contents of the config file
* @param {string} filename path to the config file
* @return {Object} config object
*/
Common.parseConfig = function(confObj, filename) {
var yamljs = require('js-yaml');
var vm = require('vm');
var isConfigFile = Common.isConfigFile(filename);
if (!filename ||
filename == 'pipe' ||
filename == 'none' ||
isConfigFile == 'json') {
var code = '(' + confObj + ')';
var sandbox = {};
return vm.runInThisContext(code, sandbox, {
filename: path.resolve(filename),
displayErrors: false,
timeout: 1000
});
}
else if (isConfigFile == 'yaml') {
return yamljs.load(confObj.toString());
}
else if (isConfigFile == 'js' || isConfigFile == 'mjs') {
var confPath = require.resolve(path.resolve(filename));
delete require.cache[confPath];
return require(confPath);
}
};
Common.retErr = function(e) {
if (!e)
return new Error('Unidentified error');
if (e instanceof Error)
return e;
return new Error(e);
}
Common.sink = {};
Common.sink.determineCron = function(app) {
if (app.cron_restart == 0 || app.cron_restart == '0') {
Common.printOut(cst.PREFIX_MSG + 'disabling cron restart');
return
}
if (app.cron_restart) {
const Croner = require('croner');
try {
Common.printOut(cst.PREFIX_MSG + 'cron restart at ' + app.cron_restart);
Croner(app.cron_restart);
} catch(ex) {
return new Error(`Cron pattern error: ${ex.message}`);
}
}
};
/**
* Handle alias (fork <=> fork_mode, cluster <=> cluster_mode)
*/
Common.sink.determineExecMode = function(app) {
if (app.exec_mode)
app.exec_mode = app.exec_mode.replace(/^(fork|cluster)$/, '$1_mode');
/**
* Here we put the default exec mode
*/
if (!app.exec_mode &&
(app.instances >= 1 || app.instances === 0 || app.instances === -1) &&
app.exec_interpreter.indexOf('node') > -1) {
app.exec_mode = 'cluster_mode';
} else if (!app.exec_mode) {
app.exec_mode = 'fork_mode';
}
if (typeof app.instances == 'undefined')
app.instances = 1;
};
var resolveNodeInterpreter = function(app) {
if (app.exec_mode && app.exec_mode.indexOf('cluster') > -1) {
Common.printError(cst.PREFIX_MSG_WARNING + chalk.bold.yellow('Choosing the Node.js version in cluster mode is not supported'));
return false;
}
var nvm_path = cst.IS_WINDOWS ? process.env.NVM_HOME : process.env.NVM_DIR;
if (!nvm_path) {
Common.printError(cst.PREFIX_MSG_ERR + chalk.red('NVM is not available in PATH'));
Common.printError(cst.PREFIX_MSG_ERR + chalk.red('Fallback to node in PATH'));
var msg = cst.IS_WINDOWS
? 'https://github.com/coreybutler/nvm-windows/releases/'
: '$ curl https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash';
Common.printOut(cst.PREFIX_MSG_ERR + chalk.bold('Install NVM:\n' + msg));
}
else {
var node_version = app.exec_interpreter.split('@')[1];
var path_to_node = cst.IS_WINDOWS
? '/v' + node_version + '/node.exe'
: semver.satisfies(node_version, '>= 0.12.0')
? '/versions/node/v' + node_version + '/bin/node'
: '/v' + node_version + '/bin/node';
var nvm_node_path = path.join(nvm_path, path_to_node);
try {
fs.accessSync(nvm_node_path);
} catch(e) {
Common.printOut(cst.PREFIX_MSG + 'Installing Node v%s', node_version);
var nvm_bin = path.join(nvm_path, 'nvm.' + (cst.IS_WINDOWS ? 'exe' : 'sh'));
var nvm_cmd = cst.IS_WINDOWS
? nvm_bin + ' install ' + node_version
: '. ' + nvm_bin + ' ; nvm install ' + node_version;
Common.printOut(cst.PREFIX_MSG + 'Executing: %s', nvm_cmd);
execSync(nvm_cmd, {
cwd: path.resolve(process.cwd()),
env: process.env,
maxBuffer: 20 * 1024 * 1024
});
// in order to support both arch, nvm for Windows renames 'node.exe' to:
// 'node32.exe' for x32 arch
// 'node64.exe' for x64 arch
if (cst.IS_WINDOWS)
nvm_node_path = nvm_node_path.replace(/node/, 'node' + process.arch.slice(1))
}
Common.printOut(cst.PREFIX_MSG + chalk.green.bold('Setting Node to v%s (path=%s)'),
node_version,
nvm_node_path);
app.exec_interpreter = nvm_node_path;
}
};
/**
* Resolve interpreter
*/
Common.sink.resolveInterpreter = function(app) {
var noInterpreter = !app.exec_interpreter;
var extName = path.extname(app.pm_exec_path);
var betterInterpreter = extItps[extName];
// No interpreter defined and correspondance in schema hashmap
if (noInterpreter && betterInterpreter) {
app.exec_interpreter = betterInterpreter;
if (betterInterpreter == "python") {
if (which('python') == null) {
if (which('python3') == null)
Common.printError(cst.PREFIX_MSG_WARNING + chalk.bold.yellow('python and python3 binaries not available in PATH'));
else
app.exec_interpreter = 'python3';
}
}
}
// Else if no Interpreter detect if process is binary
else if (noInterpreter)
app.exec_interpreter = isBinary(app.pm_exec_path) ? 'none' : 'node';
else if (app.exec_interpreter.indexOf('node@') > -1)
resolveNodeInterpreter(app);
if (app.exec_interpreter.indexOf('python') > -1)
app.env.PYTHONUNBUFFERED = '1'
if (app.exec_interpreter == 'lsc') {
app.exec_interpreter = path.resolve(__dirname, '../node_modules/.bin/lsc');
}
if (app.exec_interpreter == 'coffee') {
app.exec_interpreter = path.resolve(__dirname, '../node_modules/.bin/coffee');
}
if (app.exec_interpreter != 'none' && which(app.exec_interpreter) == null) {
// If node is not present
if (app.exec_interpreter == 'node') {
Common.warn(`Using builtin node.js version on version ${process.version}`)
app.exec_interpreter = cst.BUILTIN_NODE_PATH
}
else
throw new Error(`Interpreter ${app.exec_interpreter} is NOT AVAILABLE in PATH. (type 'which ${app.exec_interpreter}' to double check.)`)
}
return app;
};
Common.deepCopy = Common.serialize = Common.clone = function(obj) {
if (obj === null || obj === undefined) return {};
return fclone(obj);
};
Common.errMod = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
if (msg instanceof Error)
return console.error(msg.message);
return console.error(`${cst.PREFIX_MSG_MOD_ERR}${msg}`);
}
Common.err = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
if (msg instanceof Error)
return console.error(`${cst.PREFIX_MSG_ERR}${msg.message}`);
return console.error(`${cst.PREFIX_MSG_ERR}${msg}`);
}
Common.printError = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
if (msg instanceof Error)
return console.error(msg.message);
return console.error.apply(console, arguments);
};
Common.log = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
return console.log(`${cst.PREFIX_MSG}${msg}`);
}
Common.info = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
return console.log(`${cst.PREFIX_MSG_INFO}${msg}`);
}
Common.warn = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
return console.log(`${cst.PREFIX_MSG_WARNING}${msg}`);
}
Common.logMod = function(msg) {
if (process.env.PM2_SILENT || process.env.PM2_PROGRAMMATIC === 'true') return false;
return console.log(`${cst.PREFIX_MSG_MOD}${msg}`);
}
Common.printOut = function() {
if (process.env.PM2_SILENT === 'true' || process.env.PM2_PROGRAMMATIC === 'true') return false;
return console.log.apply(console, arguments);
};
/**
* Raw extend
*/
Common.extend = function(destination, source) {
if (typeof destination !== 'object') {
destination = {};
}
if (!source || typeof source !== 'object') {
return destination;
}
Object.keys(source).forEach(function(new_key) {
if (source[new_key] != '[object Object]')
destination[new_key] = source[new_key];
});
return destination;
};
/**
* This is useful when starting script programmatically
*/
Common.safeExtend = function(origin, add){
if (!add || typeof add != 'object') return origin;
//Ignore PM2's set environment variables from the nested env
var keysToIgnore = ['name', 'exec_mode', 'env', 'args', 'pm_cwd', 'exec_interpreter', 'pm_exec_path', 'node_args', 'pm_out_log_path', 'pm_err_log_path', 'pm_pid_path', 'pm_id', 'status', 'pm_uptime', 'created_at', 'windowsHide', 'username', 'merge_logs', 'kill_retry_time', 'prev_restart_delay', 'instance_var', 'unstable_restarts', 'restart_time', 'axm_actions', 'pmx_module', 'command', 'watch', 'filter_env', 'versioning', 'vizion_runing', 'MODULE_DEBUG', 'pmx', 'axm_options', 'created_at', 'watch', 'vizion', 'axm_dynamic', 'axm_monitor', 'instances', 'automation', 'autostart', 'autorestart', 'stop_exit_codes', 'unstable_restart', 'treekill', 'exit_code', 'vizion'];
var keys = Object.keys(add);
var i = keys.length;
while (i--) {
//Only copy stuff into the env that we don't have already.
if(keysToIgnore.indexOf(keys[i]) == -1 && add[keys[i]] != '[object Object]')
origin[keys[i]] = add[keys[i]];
}
return origin;
};
/**
* Extend the app.env object of with the properties taken from the
* app.env_[envName] and deploy configuration.
* Also update current json attributes
*
* Used only for Configuration file processing
*
* @param {Object} app The app object.
* @param {string} envName The given environment name.
* @param {Object} deployConf Deployment configuration object (from JSON file or whatever).
* @returns {Object} The app.env variables object.
*/
Common.mergeEnvironmentVariables = function(app_env, env_name, deploy_conf) {
var app = fclone(app_env);
var new_conf = {
env : {}
}
// Stringify possible object
for (var key in app.env) {
if (typeof app.env[key] == 'object') {
app.env[key] = JSON.stringify(app.env[key]);
}
}
/**
* Extra configuration update
*/
Object.assign(new_conf, app);
if (env_name) {
// First merge variables from deploy.production.env object as least priority.
if (deploy_conf && deploy_conf[env_name] && deploy_conf[env_name]['env']) {
Object.assign(new_conf.env, deploy_conf[env_name]['env']);
}
Object.assign(new_conf.env, app.env);
// Then, last and highest priority, merge the app.env_production object.
if ('env_' + env_name in app) {
Object.assign(new_conf.env, app['env_' + env_name]);
}
else {
Common.printOut(cst.PREFIX_MSG_WARNING + chalk.bold('Environment [%s] is not defined in process file'), env_name);
}
}
delete new_conf.exec_mode
var res = {
current_conf: {}
}
Object.assign(res, new_conf.env);
Object.assign(res.current_conf, new_conf);
// #2541 force resolution of node interpreter
if (app.exec_interpreter &&
app.exec_interpreter.indexOf('@') > -1) {
resolveNodeInterpreter(app);
res.current_conf.exec_interpreter = app.exec_interpreter
}
return res
}
/**
* This function will resolve paths, option and environment
* CALLED before 'prepare' God call (=> PROCESS INITIALIZATION)
* @method resolveAppAttributes
* @param {Object} opts
* @param {Object} opts.cwd
* @param {Object} opts.pm2_home
* @param {Object} appConf application configuration
* @return app
*/
Common.resolveAppAttributes = function(opts, conf) {
var conf_copy = fclone(conf);
var app = Common.prepareAppConf(opts, conf_copy);
if (app instanceof Error) {
throw new Error(app.message);
}
return app;
}
/**
* Verify configurations
* Called on EVERY Operation (start/restart/reload/stop...)
* @param {Array} appConfs
* @returns {Array}
*/
Common.verifyConfs = function(appConfs) {
if (!appConfs || appConfs.length == 0) {
return [];
}
// Make sure it is an Array.
appConfs = [].concat(appConfs);
var verifiedConf = [];
for (var i = 0; i < appConfs.length; i++) {
var app = appConfs[i];
if (app.exec_mode)
app.exec_mode = app.exec_mode.replace(/^(fork|cluster)$/, '$1_mode');
// JSON conf: alias cmd to script
if (app.cmd && !app.script) {
app.script = app.cmd
delete app.cmd
}
// JSON conf: alias command to script
if (app.command && !app.script) {
app.script = app.command
delete app.command
}
if (!app.env) {
app.env = {}
}
// Render an app name if not existing.
Common.renderApplicationName(app);
if (app.execute_command == true) {
app.exec_mode = 'fork'
delete app.execute_command
}
app.username = Common.getCurrentUsername();
/**
* If command is like pm2 start "python xx.py --ok"
* Then automatically start the script with bash -c and set a name eq to command
*/
if (app.script && app.script.indexOf(' ') > -1 && cst.IS_WINDOWS === false) {
var _script = app.script;
if (which('bash')) {
app.script = 'bash';
app.args = ['-c', _script];
if (!app.name) {
app.name = _script
}
}
else if (which('sh')) {
app.script = 'sh';
app.args = ['-c', _script];
if (!app.name) {
app.name = _script
}
}
else {
warn('bash or sh not available in $PATH, keeping script as is')
}
}
/**
* Add log_date_format by default
*/
if (app.time || process.env.ASZ_MODE) {
app.log_date_format = 'YYYY-MM-DDTHH:mm:ss'
}
/**
* Checks + Resolve UID/GID
* comes from pm2 --uid <> --gid <> or --user
*/
if (app.uid || app.gid || app.user) {
// 1/ Check if windows
if (cst.IS_WINDOWS === true) {
Common.printError(cst.PREFIX_MSG_ERR + '--uid and --git does not works on windows');
return new Error('--uid and --git does not works on windows');
}
// 2/ Verify that user is root (todo: verify if other has right)
if (process.env.NODE_ENV != 'test' && process.getuid && process.getuid() !== 0) {
Common.printError(cst.PREFIX_MSG_ERR + 'To use --uid and --gid please run pm2 as root');
return new Error('To use UID and GID please run PM2 as root');
}
// 3/ Resolve user info via /etc/password
var passwd = require('./tools/passwd.js')
var users
try {
users = passwd.getUsers()
} catch(e) {
Common.printError(e);
return new Error(e);
}
var user_info = users[app.uid || app.user]
if (!user_info) {
Common.printError(`${cst.PREFIX_MSG_ERR} User ${app.uid || app.user} cannot be found`);
return new Error(`${cst.PREFIX_MSG_ERR} User ${app.uid || app.user} cannot be found`);
}
app.env.HOME = user_info.homedir
app.uid = parseInt(user_info.userId)
// 4/ Resolve group id if gid is specified
if (app.gid) {
var groups
try {
groups = passwd.getGroups()
} catch(e) {
Common.printError(e);
return new Error(e);
}
var group_info = groups[app.gid]
if (!group_info) {
Common.printError(`${cst.PREFIX_MSG_ERR} Group ${app.gid} cannot be found`);
return new Error(`${cst.PREFIX_MSG_ERR} Group ${app.gid} cannot be found`);
}
app.gid = parseInt(group_info.id)
} else {
app.gid = parseInt(user_info.groupId)
}
}
/**
* Specific options of PM2.io
*/
if (process.env.PM2_DEEP_MONITORING) {
app.deep_monitoring = true;
}
if (app.automation == false) {
app.pmx = false;
}
if (app.disable_trace) {
app.trace = false
delete app.disable_trace;
}
/**
* Instances params
*/
if (app.instances == 'max') {
app.instances = 0;
}
if (typeof(app.instances) === 'string') {
app.instances = parseInt(app.instances) || 0;
}
if (app.exec_mode != 'cluster_mode' &&
!app.instances &&
typeof(app.merge_logs) == 'undefined') {
app.merge_logs = true;
}
var ret;
if (app.cron_restart) {
if ((ret = Common.sink.determineCron(app)) instanceof Error)
return ret;
}
/**
* Now validation configuration
*/
var ret = Config.validateJSON(app);
if (ret.errors && ret.errors.length > 0){
ret.errors.forEach(function(err) { warn(err) });
return new Error(ret.errors);
}
verifiedConf.push(ret.config);
}
return verifiedConf;
}
/**
* Get current username
* Called on EVERY starting app
*
* @returns {String}
*/
Common.getCurrentUsername = function(){
var current_user = '';
if (os.userInfo) {
try {
current_user = os.userInfo().username;
} catch (err) {
// For the case of unhandled error for uv_os_get_passwd
// https://github.com/Unitech/pm2/issues/3184
}
}
if(current_user === '') {
current_user = process.env.USER || process.env.LNAME || process.env.USERNAME || process.env.SUDO_USER || process.env.C9_USER || process.env.LOGNAME;
}
return current_user;
}
/**
* Render an app name if not existing.
* @param {Object} conf
*/
Common.renderApplicationName = function(conf){
if (!conf.name && conf.script){
conf.name = conf.script !== undefined ? path.basename(conf.script) : 'undefined';
var lastDot = conf.name.lastIndexOf('.');
if (lastDot > 0){
conf.name = conf.name.slice(0, lastDot);
}
}
}
/**
* Show warnings
* @param {String} warning
*/
function warn(warning){
Common.printOut(cst.PREFIX_MSG_WARNING + warning);
}

304
api.hyungi.net/node_modules/pm2/lib/Configuration.js generated vendored Normal file
View File

@@ -0,0 +1,304 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var Configuration = module.exports = {};
var fs = require('fs');
var Common = require('./Common');
var eachSeries = require('async/eachSeries');
var cst = require('../constants.js');
function splitKey(key) {
var values = [key];
if (key.indexOf('.') > -1)
values = key.match(/(?:[^."]+|"[^"]*")+/g).map(function(dt) { return dt.replace(/"/g, '') });
else if (key.indexOf(':') > -1)
values = key.match(/(?:[^:"]+|"[^"]*")+/g).map(function(dt) { return dt.replace(/"/g, '') });
return values;
}
function serializeConfiguration(json_conf) {
return JSON.stringify(json_conf, null, 4)
}
Configuration.set = function(key, value, cb) {
fs.readFile(cst.PM2_MODULE_CONF_FILE, function(err, data) {
if (err) return cb(err);
var json_conf = JSON.parse(data);
var values = splitKey(key);
if (values.length > 0) {
var levels = values;
var tmp = json_conf;
levels.forEach(function(key, index) {
if (index == levels.length -1)
tmp[key] = value;
else if (!tmp[key]) {
tmp[key] = {};
tmp = tmp[key];
}
else {
if (typeof(tmp[key]) != 'object')
tmp[key] = {};
tmp = tmp[key];
}
});
}
else {
if (json_conf[key] && typeof(json_conf[key]) === 'string')
Common.printOut(cst.PREFIX_MSG + 'Replacing current value key %s by %s', key, value);
json_conf[key] = value;
}
fs.writeFile(cst.PM2_MODULE_CONF_FILE, serializeConfiguration(json_conf), function(err, data) {
if (err) return cb(err);
return cb(null, json_conf);
});
return false;
});
};
Configuration.unset = function(key, cb) {
fs.readFile(cst.PM2_MODULE_CONF_FILE, function(err, data) {
if (err) return cb(err);
var json_conf = JSON.parse(data);
var values = splitKey(key);
if (values.length > 0) {
var levels = values;
var tmp = json_conf;
levels.forEach(function(key, index) {
if (index == levels.length -1)
delete tmp[key];
else if (!tmp[key]) {
tmp[key] = {};
tmp = tmp[key];
}
else {
if (typeof(tmp[key]) != 'object')
tmp[key] = {};
tmp = tmp[key];
}
});
}
else
delete json_conf[key];
if (err) return cb(err);
if (key === 'all')
json_conf = {};
fs.writeFile(cst.PM2_MODULE_CONF_FILE, serializeConfiguration(json_conf), function(err, data) {
if (err) return cb(err);
return cb(null, json_conf);
});
return false;
});
}
Configuration.setSyncIfNotExist = function(key, value) {
try {
var conf = JSON.parse(fs.readFileSync(cst.PM2_MODULE_CONF_FILE));
} catch(e) {
return null;
}
var values = splitKey(key);
var exists = false;
if (values.length > 1 && conf && conf[values[0]]) {
exists = Object.keys(conf[values[0]]).some(function(key) {
if (key == values[1])
return true;
return false;
});
}
if (exists === false)
return Configuration.setSync(key, value);
return null;
};
Configuration.setSync = function(key, value) {
try {
var data = fs.readFileSync(cst.PM2_MODULE_CONF_FILE);
} catch(e) {
return null;
}
var json_conf = JSON.parse(data);
var values = splitKey(key);
if (values.length > 0) {
var levels = values;
var tmp = json_conf;
levels.forEach(function(key, index) {
if (index == levels.length -1)
tmp[key] = value;
else if (!tmp[key]) {
tmp[key] = {};
tmp = tmp[key];
}
else {
if (typeof(tmp[key]) != 'object')
tmp[key] = {};
tmp = tmp[key];
}
});
}
else {
if (json_conf[key] && typeof(json_conf[key]) === 'string')
Common.printOut(cst.PREFIX_MSG + 'Replacing current value key %s by %s', key, value);
json_conf[key] = value;
}
if (key === 'all')
json_conf = {};
try {
fs.writeFileSync(cst.PM2_MODULE_CONF_FILE, serializeConfiguration(json_conf));
return json_conf;
} catch(e) {
console.error(e.message);
return null;
}
};
Configuration.unsetSync = function(key) {
try {
var data = fs.readFileSync(cst.PM2_MODULE_CONF_FILE);
} catch(e) {
return null;
}
var json_conf = JSON.parse(data);
var values = splitKey(key);
if (values.length > 0) {
var levels = values;
var tmp = json_conf;
levels.forEach(function(key, index) {
if (index == levels.length -1)
delete tmp[key];
else if (!tmp[key]) {
tmp[key] = {};
tmp = tmp[key];
}
else {
if (typeof(tmp[key]) != 'object')
tmp[key] = {};
tmp = tmp[key];
}
});
}
else
delete json_conf[key];
if (key === 'all')
json_conf = {};
try {
fs.writeFileSync(cst.PM2_MODULE_CONF_FILE, serializeConfiguration(json_conf));
} catch(e) {
console.error(e.message);
return null;
}
};
Configuration.multiset = function(serial, cb) {
var arrays = [];
serial = serial.match(/(?:[^ "]+|"[^"]*")+/g);
while (serial.length > 0)
arrays.push(serial.splice(0, 2));
eachSeries(arrays, function(el, next) {
Configuration.set(el[0], el[1], next);
}, cb);
};
Configuration.get = function(key, cb) {
Configuration.getAll(function(err, data) {
var climb = splitKey(key);
climb.some(function(val) {
if (!data[val]) {
data = null;
return true;
}
data = data[val];
return false;
});
if (!data) return cb({err : 'Unknown key'}, null);
return cb(null, data);
});
};
Configuration.getSync = function(key) {
try {
var data = Configuration.getAllSync();
} catch(e) {
return null;
}
var climb = splitKey(key);
climb.some(function(val) {
if (!data[val]) {
data = null;
return true;
}
data = data[val];
return false;
});
if (!data) return null;
return data;
};
Configuration.getAll = function(cb) {
fs.readFile(cst.PM2_MODULE_CONF_FILE, function(err, data) {
if (err) return cb(err);
return cb(null, JSON.parse(data));
});
};
Configuration.getAllSync = function() {
try {
return JSON.parse(fs.readFileSync(cst.PM2_MODULE_CONF_FILE));
} catch(e) {
console.error(e.stack || e);
return {};
}
};

455
api.hyungi.net/node_modules/pm2/lib/Daemon.js generated vendored Normal file
View File

@@ -0,0 +1,455 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var debug = require('debug')('pm2:daemon');
var pkg = require('../package.json');
var cst = require('../constants.js');
var rpc = require('pm2-axon-rpc');
var axon = require('pm2-axon');
var domain = require('domain');
var Utility = require('./Utility.js');
var util = require('util');
var fs = require('fs');
var God = require('./God');
var eachLimit = require('async/eachLimit');
var fmt = require('./tools/fmt.js');
var semver = require('semver');
var Daemon = module.exports = function(opts) {
if (!opts) opts = {};
this.ignore_signals = opts.ignore_signals || false;
this.rpc_socket_ready = false;
this.pub_socket_ready = false;
this.pub_socket_file = opts.pub_socket_file || cst.DAEMON_PUB_PORT;
this.rpc_socket_file = opts.rpc_socket_file || cst.DAEMON_RPC_PORT;
this.pid_path = opts.pid_file || cst.PM2_PID_FILE_PATH;
};
Daemon.prototype.start = function() {
var that = this;
var d = domain.create();
d.once('error', function(err) {
fmt.sep();
fmt.title('PM2 global error caught');
fmt.field('Time', new Date());
console.error(err.message);
console.error(err.stack);
fmt.sep();
console.error('[PM2] Resurrecting PM2');
var path = cst.IS_WINDOWS ? __dirname + '/../bin/pm2' : process.env['_'];
var fork_new_pm2 = require('child_process').spawn('node', [path, 'update'], {
detached: true,
windowsHide: true,
stdio: 'inherit'
});
fork_new_pm2.on('close', function() {
console.log('PM2 successfully forked');
process.exit(0);
})
});
d.run(function() {
that.innerStart();
});
}
Daemon.prototype.innerStart = function(cb) {
var that = this;
if (!cb) cb = function() {
fmt.sep();
fmt.title('New PM2 Daemon started');
fmt.field('Time', new Date());
fmt.field('PM2 version', pkg.version);
fmt.field('Node.js version', process.versions.node);
fmt.field('Current arch', process.arch);
fmt.field('PM2 home', cst.PM2_HOME);
fmt.field('PM2 PID file', that.pid_path);
fmt.field('RPC socket file', that.rpc_socket_file);
fmt.field('BUS socket file', that.pub_socket_file);
fmt.field('Application log path', cst.DEFAULT_LOG_PATH);
fmt.field('Worker Interval', cst.WORKER_INTERVAL);
fmt.field('Process dump file', cst.DUMP_FILE_PATH);
fmt.field('Concurrent actions', cst.CONCURRENT_ACTIONS);
fmt.field('SIGTERM timeout', cst.KILL_TIMEOUT);
fmt.sep();
};
// Write Daemon PID into file
try {
fs.writeFileSync(that.pid_path, process.pid.toString());
} catch (e) {
console.error(e.stack || e);
}
if (this.ignore_signals != true)
this.handleSignals();
/**
* Pub system for real time notifications
*/
this.pub = axon.socket('pub-emitter');
this.pub_socket = this.pub.bind(this.pub_socket_file);
this.pub_socket.once('bind', function() {
fs.chmod(that.pub_socket_file, '775', function(e) {
if (e) console.error(e);
try {
if (process.env.PM2_SOCKET_USER && process.env.PM2_SOCKET_GROUP)
fs.chown(that.pub_socket_file,
parseInt(process.env.PM2_SOCKET_USER),
parseInt(process.env.PM2_SOCKET_GROUP), function(e) {
if (e) console.error(e);
});
} catch(e) {
console.error(e);
}
});
that.pub_socket_ready = true;
that.sendReady(cb);
});
/**
* Rep/Req - RPC system to interact with God
*/
this.rep = axon.socket('rep');
var server = new rpc.Server(this.rep);
this.rpc_socket = this.rep.bind(this.rpc_socket_file);
this.rpc_socket.once('bind', function() {
fs.chmod(that.rpc_socket_file, '775', function(e) {
if (e) console.error(e);
try {
if (process.env.PM2_SOCKET_USER && process.env.PM2_SOCKET_GROUP)
fs.chown(that.rpc_socket_file,
parseInt(process.env.PM2_SOCKET_USER),
parseInt(process.env.PM2_SOCKET_GROUP), function(e) {
if (e) console.error(e);
});
} catch(e) {
console.error(e);
}
});
that.rpc_socket_ready = true;
that.sendReady(cb);
});
/**
* Memory Snapshot
*/
function profile(type, msg, cb) {
if (semver.satisfies(process.version, '< 8'))
return cb(null, { error: 'Node.js is not on right version' })
var cmd
if (type === 'cpu') {
cmd = {
enable: 'Profiler.enable',
start: 'Profiler.start',
stop: 'Profiler.stop',
disable: 'Profiler.disable'
}
}
if (type == 'mem') {
cmd = {
enable: 'HeapProfiler.enable',
start: 'HeapProfiler.startSampling',
stop: 'HeapProfiler.stopSampling',
disable: 'HeapProfiler.disable'
}
}
const inspector = require('inspector')
var session = new inspector.Session()
session.connect()
var timeout = msg.timeout || 5000
session.post(cmd.enable, (err, data) => {
if (err) return cb(null, { error: err.message || err })
console.log(`Starting ${cmd.start}`)
session.post(cmd.start, (err, data) => {
if (err) return cb(null, { error: err.message || err })
setTimeout(() => {
session.post(cmd.stop, (err, data) => {
if (err) return cb(null, { error: err.message || err })
const profile = data.profile
console.log(`Stopping ${cmd.stop}`)
session.post(cmd.disable)
fs.writeFile(msg.pwd, JSON.stringify(profile), (err) => {
if (err) return cb(null, { error: err.message || err })
return cb(null, { file : msg.pwd })
})
})
}, timeout)
})
})
}
server.expose({
killMe : that.close.bind(this),
profileCPU : profile.bind(this, 'cpu'),
profileMEM : profile.bind(this, 'mem'),
prepare : God.prepare,
getMonitorData : God.getMonitorData,
startProcessId : God.startProcessId,
stopProcessId : God.stopProcessId,
restartProcessId : God.restartProcessId,
deleteProcessId : God.deleteProcessId,
sendLineToStdin : God.sendLineToStdin,
softReloadProcessId : God.softReloadProcessId,
reloadProcessId : God.reloadProcessId,
duplicateProcessId : God.duplicateProcessId,
resetMetaProcessId : God.resetMetaProcessId,
stopWatch : God.stopWatch,
startWatch : God.startWatch,
toggleWatch : God.toggleWatch,
notifyByProcessId : God.notifyByProcessId,
notifyKillPM2 : God.notifyKillPM2,
monitor : God.monitor,
unmonitor : God.unmonitor,
msgProcess : God.msgProcess,
sendDataToProcessId : God.sendDataToProcessId,
sendSignalToProcessId : God.sendSignalToProcessId,
sendSignalToProcessName : God.sendSignalToProcessName,
ping : God.ping,
getVersion : God.getVersion,
getReport : God.getReport,
reloadLogs : God.reloadLogs
});
this.startLogic();
}
Daemon.prototype.close = function(opts, cb) {
var that = this;
God.bus.emit('pm2:kill', {
status : 'killed',
msg : 'pm2 has been killed via CLI'
});
if (God.system_infos_proc !== null)
God.system_infos_proc.kill()
/**
* Cleanly kill pm2
*/
that.rpc_socket.close(function() {
that.pub_socket.close(function() {
// notify cli that the daemon is shuting down (only under unix since windows doesnt handle signals)
if (cst.IS_WINDOWS === false) {
try {
process.kill(parseInt(opts.pid), 'SIGQUIT');
} catch(e) {
console.error('Could not send SIGQUIT to CLI');
}
}
try {
fs.unlinkSync(that.pid_path);
} catch(e) {}
console.log('PM2 successfully stopped');
setTimeout(function() {
process.exit(cst.SUCCESS_EXIT);
}, 2);
});
});
}
Daemon.prototype.handleSignals = function() {
var that = this;
process.on('SIGTERM', that.gracefullExit.bind(this));
process.on('SIGINT', that.gracefullExit.bind(this));
process.on('SIGHUP', function() {});
process.on('SIGQUIT', that.gracefullExit.bind(this));
process.on('SIGUSR2', function() {
God.reloadLogs({}, function() {});
});
}
Daemon.prototype.sendReady = function(cb) {
// Send ready message to Client
if (this.rpc_socket_ready == true && this.pub_socket_ready == true) {
cb(null, {
pid : process.pid,
pm2_version : pkg.version
});
if (typeof(process.send) != 'function')
return false;
process.send({
online : true,
success : true,
pid : process.pid,
pm2_version : pkg.version
});
};
}
Daemon.prototype.gracefullExit = function() {
var that = this;
// never execute multiple gracefullExit simultaneously
// this can lead to loss of some apps in dump file
if (this.isExiting) return
this.isExiting = true
God.bus.emit('pm2:kill', {
status : 'killed',
msg : 'pm2 has been killed by SIGNAL'
});
console.log('pm2 has been killed by signal, dumping process list before exit...');
if (God.system_infos_proc !== null)
God.system_infos_proc.kill()
God.dumpProcessList(function() {
var processes = God.getFormatedProcesses();
eachLimit(processes, 1, function(proc, next) {
console.log('Deleting process %s', proc.pm2_env.pm_id);
God.deleteProcessId(proc.pm2_env.pm_id, function() {
return next();
});
}, function(err) {
try {
fs.unlinkSync(that.pid_path);
} catch(e) {}
setTimeout(function() {
that.isExiting = false
console.log('Exited peacefully');
process.exit(cst.SUCCESS_EXIT);
}, 2);
});
});
}
Daemon.prototype.startLogic = function() {
var that = this;
/**
* Action treatment specifics
* Attach actions to pm2_env.axm_actions variables (name + options)
*/
God.bus.on('axm:action', function axmActions(msg) {
var pm2_env = msg.process;
var exists = false;
var axm_action = msg.data;
if (!pm2_env || !God.clusters_db[pm2_env.pm_id])
return console.error('AXM ACTION Unknown id %s', pm2_env.pm_id);
if (!God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions)
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions = [];
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions.forEach(function(actions) {
if (actions.action_name == axm_action.action_name)
exists = true;
});
if (exists === false) {
debug('Adding action', axm_action);
God.clusters_db[pm2_env.pm_id].pm2_env.axm_actions.push(axm_action);
}
msg = null;
});
/**
* Configure module
*/
God.bus.on('axm:option:configuration', function axmMonitor(msg) {
if (!msg.process)
return console.error('[axm:option:configuration] no process defined');
if (!God.clusters_db[msg.process.pm_id])
return console.error('[axm:option:configuration] Unknown id %s', msg.process.pm_id);
try {
// Application Name nverride
if (msg.data.name)
God.clusters_db[msg.process.pm_id].pm2_env.name = msg.data.name;
Object.keys(msg.data).forEach(function(conf_key) {
God.clusters_db[msg.process.pm_id].pm2_env.axm_options[conf_key] = Utility.clone(msg.data[conf_key]);
});
} catch(e) {
console.error(e.stack || e);
}
msg = null;
});
/**
* Process monitoring data (probes)
*/
God.bus.on('axm:monitor', function axmMonitor(msg) {
if (!msg.process)
return console.error('[axm:monitor] no process defined');
if (!msg.process || !God.clusters_db[msg.process.pm_id])
return console.error('AXM MONITOR Unknown id %s', msg.process.pm_id);
Object.assign(God.clusters_db[msg.process.pm_id].pm2_env.axm_monitor, Utility.clone(msg.data));
msg = null;
});
/**
* Broadcast messages
*/
God.bus.onAny(function(event, data_v) {
if (['axm:action',
'axm:monitor',
'axm:option:setPID',
'axm:option:configuration'].indexOf(event) > -1) {
data_v = null;
return false;
}
that.pub.emit(event, Utility.clone(data_v));
data_v = null;
});
};
if (require.main === module) {
process.title = process.env.PM2_DAEMON_TITLE || 'PM2 v' + pkg.version + ': God Daemon (' + process.env.PM2_HOME + ')';
var daemon = new Daemon();
daemon.start();
}

37
api.hyungi.net/node_modules/pm2/lib/Event.js generated vendored Normal file
View File

@@ -0,0 +1,37 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var Utility = require('./Utility.js');
module.exports = function(God) {
God.notify = function(action_name, data, manually) {
God.bus.emit('process:event', {
event : action_name,
manually : typeof(manually) == 'undefined' ? false : true,
process : Utility.formatCLU(data),
at : Utility.getDate()
});
};
God.notifyByProcessId = function(opts, cb) {
if (typeof(opts.id) === 'undefined') { return cb(new Error('process id missing')); }
var proc = God.clusters_db[opts.id];
if (!proc) { return cb(new Error('process id doesnt exists')); }
God.bus.emit('process:event', {
event : opts.action_name,
manually : typeof(opts.manually) == 'undefined' ? false : true,
process : Utility.formatCLU(proc),
at : Utility.getDate()
});
process.nextTick(function() {
return cb ? cb(null) : false;
});
return false;
};
};

588
api.hyungi.net/node_modules/pm2/lib/God.js generated vendored Normal file
View File

@@ -0,0 +1,588 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
/******************************
* ______ _______ ______
* | __ \ | |__ |
* | __/ | __|
* |___| |__|_|__|______|
*
* Main Daemon side file
*
******************************/
var cluster = require('cluster');
var numCPUs = require('os').cpus() ? require('os').cpus().length : 1;
var path = require('path');
var EventEmitter2 = require('eventemitter2').EventEmitter2;
var fs = require('fs');
var vizion = require('vizion');
var debug = require('debug')('pm2:god');
var Utility = require('./Utility');
var cst = require('../constants.js');
var timesLimit = require('async/timesLimit');
var Configuration = require('./Configuration.js');
/**
* Override cluster module configuration
*/
cluster.setupMaster({
windowsHide: true,
exec : path.resolve(path.dirname(module.filename), 'ProcessContainer.js')
});
/**
* Expose God
*/
var God = module.exports = {
next_id : 0,
clusters_db : {},
configuration: {},
started_at : Date.now(),
system_infos_proc: null,
system_infos: null,
bus : new EventEmitter2({
wildcard: true,
delimiter: ':',
maxListeners: 1000
})
};
Utility.overrideConsole(God.bus);
/**
* Populate God namespace
*/
require('./Event.js')(God);
require('./God/Methods.js')(God);
require('./God/ForkMode.js')(God);
require('./God/ClusterMode.js')(God);
require('./God/Reload')(God);
require('./God/ActionMethods')(God);
require('./Watcher')(God);
God.init = function() {
require('./Worker.js')(this)
God.system_infos_proc = null
this.configuration = Configuration.getSync('pm2')
setTimeout(function() {
God.Worker.start()
}, 500)
}
God.writeExitSeparator = function(pm2_env, code, signal) {
try {
var exit_sep = `[PM2][${new Date().toISOString()}] app exited`
if (code)
exit_sep += `itself with exit code: ${code}`
if (signal)
exit_sep += `by an external signal: ${signal}`
exit_sep += '\n'
if (pm2_env.pm_out_log_path)
fs.writeFileSync(pm2_env.pm_out_log_path, exit_sep)
if (pm2_env.pm_err_log_path)
fs.writeFileSync(pm2_env.pm_err_log_path, exit_sep)
if (pm2_env.pm_log_path)
fs.writeFileSync(pm2_env.pm_log_path, exit_sep)
} catch(e) {
}
}
/**
* Init new process
*/
God.prepare = function prepare (env, cb) {
// generate a new unique id for each processes
env.env.unique_id = Utility.generateUUID()
// if the app is standalone, no multiple instance
if (typeof env.instances === 'undefined') {
env.vizion_running = false;
if (env.env && env.env.vizion_running) env.env.vizion_running = false;
if (env.status == cst.STOPPED_STATUS) {
env.pm_id = God.getNewId()
var clu = {
pm2_env : env,
process: {
}
}
God.clusters_db[env.pm_id] = clu
God.registerCron(env)
return cb(null, [ God.clusters_db[env.pm_id] ])
}
return God.executeApp(env, function (err, clu) {
if (err) return cb(err);
God.notify('start', clu, true);
return cb(null, [ Utility.clone(clu) ]);
});
}
// find how many replicate the user want
env.instances = parseInt(env.instances);
if (env.instances === 0) {
env.instances = numCPUs;
} else if (env.instances < 0) {
env.instances += numCPUs;
}
if (env.instances <= 0) {
env.instances = 1;
}
timesLimit(env.instances, 1, function (n, next) {
env.vizion_running = false;
if (env.env && env.env.vizion_running) {
env.env.vizion_running = false;
}
God.injectVariables(env, function inject (err, _env) {
if (err) return next(err);
return God.executeApp(Utility.clone(_env), function (err, clu) {
if (err) return next(err);
God.notify('start', clu, true);
// here call next wihtout an array because
// async.times aggregate the result into an array
return next(null, Utility.clone(clu));
});
});
}, cb);
};
/**
* Launch the specified script (present in env)
* @api private
* @method executeApp
* @param {Mixed} env
* @param {Function} cb
* @return Literal
*/
God.executeApp = function executeApp(env, cb) {
var env_copy = Utility.clone(env);
Utility.extend(env_copy, env_copy.env);
env_copy['status'] = env.autostart ? cst.LAUNCHING_STATUS : cst.STOPPED_STATUS;
env_copy['pm_uptime'] = Date.now();
env_copy['axm_actions'] = [];
env_copy['axm_monitor'] = {};
env_copy['axm_options'] = {};
env_copy['axm_dynamic'] = {};
env_copy['vizion_running'] =
env_copy['vizion_running'] !== undefined ? env_copy['vizion_running'] : false;
if (!env_copy.created_at)
env_copy['created_at'] = Date.now();
/**
* Enter here when it's the first time that the process is created
* 1 - Assign a new id
* 2 - Reset restart time and unstable_restarts
* 3 - Assign a log file name depending on the id
* 4 - If watch option is set, look for changes
*/
if (env_copy['pm_id'] === undefined) {
env_copy['pm_id'] = God.getNewId();
env_copy['restart_time'] = 0;
env_copy['unstable_restarts'] = 0;
// add -pm_id to pid file
env_copy.pm_pid_path = env_copy.pm_pid_path.replace(/-[0-9]+\.pid$|\.pid$/g, '-' + env_copy['pm_id'] + '.pid');
// If merge option, dont separate the logs
if (!env_copy['merge_logs']) {
['', '_out', '_err'].forEach(function(k){
var key = 'pm' + k + '_log_path';
env_copy[key] && (env_copy[key] = env_copy[key].replace(/-[0-9]+\.log$|\.log$/g, '-' + env_copy['pm_id'] + '.log'));
});
}
// Initiate watch file
if (env_copy['watch']) {
God.watch.enable(env_copy);
}
}
God.registerCron(env_copy)
if (env_copy['autostart'] === false) {
var clu = {pm2_env: env_copy, process: {pid: 0}};
God.clusters_db[env_copy.pm_id] = clu;
return cb(null, clu);
}
/** Callback when application is launched */
var readyCb = function ready(proc) {
// If vizion enabled run versioning retrieval system
if (proc.pm2_env.vizion !== false && proc.pm2_env.vizion !== "false")
God.finalizeProcedure(proc);
else
God.notify('online', proc);
if (proc.pm2_env.status !== cst.ERRORED_STATUS)
proc.pm2_env.status = cst.ONLINE_STATUS
console.log(`App [${proc.pm2_env.name}:${proc.pm2_env.pm_id}] online`);
if (cb) cb(null, proc);
}
if (env_copy.exec_mode === 'cluster_mode') {
/**
* Cluster mode logic (for NodeJS apps)
*/
God.nodeApp(env_copy, function nodeApp(err, clu) {
if (cb && err) return cb(err);
if (err) return false;
var old_env = God.clusters_db[clu.pm2_env.pm_id];
if (old_env) {
old_env = null;
God.clusters_db[clu.pm2_env.pm_id] = null;
}
God.clusters_db[clu.pm2_env.pm_id] = clu;
clu.once('error', function(err) {
console.error(err.stack || err);
try {
clu.destroy && clu.destroy();
}
catch (e) {
console.error(e.stack || e);
God.handleExit(clu, cst.ERROR_EXIT);
}
});
clu.once('disconnect', function() {
console.log('App name:%s id:%s disconnected', clu.pm2_env.name, clu.pm2_env.pm_id);
});
clu.once('exit', function cluExit(code, signal) {
//God.writeExitSeparator(clu.pm2_env, code, signal)
God.handleExit(clu, code || 0, signal || 'SIGINT');
});
return clu.once('online', function () {
if (!clu.pm2_env.wait_ready)
return readyCb(clu);
// Timeout if the ready message has not been sent before listen_timeout
var ready_timeout = setTimeout(function() {
God.bus.removeListener('process:msg', listener)
return readyCb(clu)
}, clu.pm2_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
var listener = function (packet) {
if (packet.raw === 'ready' &&
packet.process.name === clu.pm2_env.name &&
packet.process.pm_id === clu.pm2_env.pm_id) {
clearTimeout(ready_timeout);
God.bus.removeListener('process:msg', listener)
return readyCb(clu)
}
}
God.bus.on('process:msg', listener);
});
});
}
else {
/**
* Fork mode logic
*/
God.forkMode(env_copy, function forkMode(err, clu) {
if (cb && err) return cb(err);
if (err) return false;
var old_env = God.clusters_db[clu.pm2_env.pm_id];
if (old_env) old_env = null;
God.clusters_db[env_copy.pm_id] = clu;
clu.once('error', function cluError(err) {
console.error(err.stack || err);
try {
clu.kill && clu.kill();
}
catch (e) {
console.error(e.stack || e);
God.handleExit(clu, cst.ERROR_EXIT);
}
});
clu.once('exit', function cluClose(code, signal) {
//God.writeExitSeparator(clu.pm2_env, code, signal)
if (clu.connected === true)
clu.disconnect && clu.disconnect();
clu._reloadLogs = null;
return God.handleExit(clu, code || 0, signal);
});
if (!clu.pm2_env.wait_ready)
return readyCb(clu);
// Timeout if the ready message has not been sent before listen_timeout
var ready_timeout = setTimeout(function() {
God.bus.removeListener('process:msg', listener)
return readyCb(clu)
}, clu.pm2_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
var listener = function (packet) {
if (packet.raw === 'ready' &&
packet.process.name === clu.pm2_env.name &&
packet.process.pm_id === clu.pm2_env.pm_id) {
clearTimeout(ready_timeout);
God.bus.removeListener('process:msg', listener)
return readyCb(clu)
}
}
God.bus.on('process:msg', listener);
});
}
return false;
};
/**
* Handle logic when a process exit (Node or Fork)
* @method handleExit
* @param {} clu
* @param {} exit_code
* @return
*/
God.handleExit = function handleExit(clu, exit_code, kill_signal) {
console.log(`App [${clu.pm2_env.name}:${clu.pm2_env.pm_id}] exited with code [${exit_code}] via signal [${kill_signal || 'SIGINT'}]`)
var proc = this.clusters_db[clu.pm2_env.pm_id];
if (!proc) {
console.error('Process undefined ? with process id ', clu.pm2_env.pm_id);
return false;
}
var stopExitCodes = proc.pm2_env.stop_exit_codes !== undefined && proc.pm2_env.stop_exit_codes !== null ? proc.pm2_env.stop_exit_codes : [];
if (!Array.isArray(stopExitCodes)) {
stopExitCodes = [stopExitCodes];
}
var stopping = (proc.pm2_env.status == cst.STOPPING_STATUS
|| proc.pm2_env.status == cst.STOPPED_STATUS
|| proc.pm2_env.status == cst.ERRORED_STATUS)
|| (proc.pm2_env.autorestart === false || proc.pm2_env.autorestart === "false")
|| (stopExitCodes.map((strOrNum) => typeof strOrNum === 'string' ? parseInt(strOrNum, 10) : strOrNum)
.includes(exit_code));
var overlimit = false;
if (stopping) proc.process.pid = 0;
// Reset probes and actions
if (proc.pm2_env.axm_actions) proc.pm2_env.axm_actions = [];
if (proc.pm2_env.axm_monitor) proc.pm2_env.axm_monitor = {};
if (proc.pm2_env.status != cst.ERRORED_STATUS &&
proc.pm2_env.status != cst.STOPPING_STATUS)
proc.pm2_env.status = cst.STOPPED_STATUS;
if (proc.pm2_env.pm_id.toString().indexOf('_old_') !== 0) {
try {
fs.unlinkSync(proc.pm2_env.pm_pid_path);
} catch (e) {
debug('Error when unlinking pid file', e);
}
}
/**
* Avoid infinite reloop if an error is present
*/
// If the process has been created less than 15seconds ago
// And if the process has an uptime less than a second
var min_uptime = typeof(proc.pm2_env.min_uptime) !== 'undefined' ? proc.pm2_env.min_uptime : 1000;
var max_restarts = typeof(proc.pm2_env.max_restarts) !== 'undefined' ? proc.pm2_env.max_restarts : 16;
if ((Date.now() - proc.pm2_env.created_at) < (min_uptime * max_restarts)) {
if ((Date.now() - proc.pm2_env.pm_uptime) < min_uptime) {
// Increment unstable restart
proc.pm2_env.unstable_restarts += 1;
}
}
if (proc.pm2_env.unstable_restarts >= max_restarts) {
// Too many unstable restart in less than 15 seconds
// Set the process as 'ERRORED'
// And stop restarting it
proc.pm2_env.status = cst.ERRORED_STATUS;
proc.process.pid = 0;
console.log('Script %s had too many unstable restarts (%d). Stopped. %j',
proc.pm2_env.pm_exec_path,
proc.pm2_env.unstable_restarts,
proc.pm2_env.status);
God.notify('restart overlimit', proc);
proc.pm2_env.unstable_restarts = 0;
proc.pm2_env.created_at = null;
overlimit = true;
}
if (typeof(exit_code) !== 'undefined') proc.pm2_env.exit_code = exit_code;
God.notify('exit', proc);
if (God.pm2_being_killed) {
//console.log('[HandleExit] PM2 is being killed, stopping restart procedure...');
return false;
}
var restart_delay = 0;
if (proc.pm2_env.restart_delay !== undefined &&
!isNaN(parseInt(proc.pm2_env.restart_delay))) {
proc.pm2_env.status = cst.WAITING_RESTART;
restart_delay = parseInt(proc.pm2_env.restart_delay);
}
if (proc.pm2_env.exp_backoff_restart_delay !== undefined &&
!isNaN(parseInt(proc.pm2_env.exp_backoff_restart_delay))) {
proc.pm2_env.status = cst.WAITING_RESTART;
if (!proc.pm2_env.prev_restart_delay) {
proc.pm2_env.prev_restart_delay = proc.pm2_env.exp_backoff_restart_delay
restart_delay = proc.pm2_env.exp_backoff_restart_delay
}
else {
proc.pm2_env.prev_restart_delay = Math.floor(Math.min(15000, proc.pm2_env.prev_restart_delay * 1.5))
restart_delay = proc.pm2_env.prev_restart_delay
}
console.log(`App [${clu.pm2_env.name}:${clu.pm2_env.pm_id}] will restart in ${restart_delay}ms`)
}
if (!stopping && !overlimit) {
//make this property unenumerable
Object.defineProperty(proc.pm2_env, 'restart_task', {configurable: true, writable: true});
proc.pm2_env.restart_task = setTimeout(function() {
proc.pm2_env.restart_time += 1;
God.executeApp(proc.pm2_env);
}, restart_delay);
}
return false;
};
/**
* @method finalizeProcedure
* @param proc {Object}
* @return
*/
God.finalizeProcedure = function finalizeProcedure(proc) {
var last_path = '';
var current_path = proc.pm2_env.cwd || path.dirname(proc.pm2_env.pm_exec_path);
var proc_id = proc.pm2_env.pm_id;
proc.pm2_env.version = Utility.findPackageVersion(proc.pm2_env.pm_exec_path || proc.pm2_env.cwd);
if (proc.pm2_env.vizion_running === true) {
debug('Vizion is already running for proc id: %d, skipping this round', proc_id);
return God.notify('online', proc);
}
proc.pm2_env.vizion_running = true;
vizion.analyze({folder : current_path}, function recur_path(err, meta){
var proc = God.clusters_db[proc_id];
if (err)
debug(err.stack || err);
if (!proc ||
!proc.pm2_env ||
proc.pm2_env.status == cst.STOPPED_STATUS ||
proc.pm2_env.status == cst.STOPPING_STATUS ||
proc.pm2_env.status == cst.ERRORED_STATUS) {
return console.error('Cancelling versioning data parsing');
}
proc.pm2_env.vizion_running = false;
if (!err) {
proc.pm2_env.versioning = meta;
proc.pm2_env.versioning.repo_path = current_path;
God.notify('online', proc);
}
else if (err && current_path === last_path) {
proc.pm2_env.versioning = null;
God.notify('online', proc);
}
else {
last_path = current_path;
current_path = path.dirname(current_path);
proc.pm2_env.vizion_running = true;
vizion.analyze({folder : current_path}, recur_path);
}
return false;
});
};
/**
* Inject variables into processes
* @param {Object} env environnement to be passed to the process
* @param {Function} cb invoked with <err, env>
*/
God.injectVariables = function injectVariables (env, cb) {
// allow to override the key of NODE_APP_INSTANCE if wanted
var instanceKey = process.env.PM2_PROCESS_INSTANCE_VAR || env.instance_var;
// we need to find the last NODE_APP_INSTANCE used
var instances = Object.keys(God.clusters_db)
.map(function (procId) {
return God.clusters_db[procId];
}).filter(function (proc) {
return proc.pm2_env.name === env.name &&
typeof proc.pm2_env[instanceKey] !== 'undefined';
}).map(function (proc) {
return proc.pm2_env[instanceKey];
}).sort(function (a, b) {
return b - a;
});
// default to last one + 1
var instanceNumber = typeof instances[0] === 'undefined' ? 0 : instances[0] + 1;
// but try to find a one available
for (var i = 0; i < instances.length; i++) {
if (instances.indexOf(i) === -1) {
instanceNumber = i;
break;
}
}
env[instanceKey] = instanceNumber;
// if using increment_var, we need to increment it
if (env.increment_var) {
var lastIncrement = Object.keys(God.clusters_db)
.map(function (procId) {
return God.clusters_db[procId];
}).filter(function (proc) {
return proc.pm2_env.name === env.name &&
typeof proc.pm2_env[env.increment_var] !== 'undefined';
}).map(function (proc) {
return Number(proc.pm2_env[env.increment_var]);
}).sort(function (a, b) {
return b - a;
})[0];
// inject a incremental variable
var defaut = Number(env.env[env.increment_var]) || 0;
env[env.increment_var] = typeof lastIncrement === 'undefined' ? defaut : lastIncrement + 1;
env.env[env.increment_var] = env[env.increment_var];
}
return cb(null, env);
};
God.init()

View File

@@ -0,0 +1,909 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
/**
* @file ActionMethod like restart, stop, monitor... are here
* @author Alexandre Strzelewicz <as@unitech.io>
* @project PM2
*/
var fs = require('fs');
var path = require('path');
var eachLimit = require('async/eachLimit');
var os = require('os');
var p = path;
var cst = require('../../constants.js');
var pkg = require('../../package.json');
var pidusage = require('pidusage');
var util = require('util');
var debug = require('debug')('pm2:ActionMethod');
var Utility = require('../Utility');
/**
* Description
* @method exports
* @param {} God
* @return
*/
module.exports = function(God) {
/**
* Description
* @method getMonitorData
* @param {} env
* @param {} cb
* @return
*/
God.getMonitorData = function getMonitorData(env, cb) {
var processes = God.getFormatedProcesses();
var pids = processes.filter(filterBadProcess)
.map(function(pro, i) {
var pid = getProcessId(pro)
return pid;
})
// No pids, return empty statistics
if (pids.length === 0) {
return cb(null, processes.map(function(pro) {
pro['monit'] = {
memory : 0,
cpu : 0
};
return pro
}))
}
pidusage(pids, function retPidUsage(err, statistics) {
// Just log, we'll set empty statistics
if (err) {
console.error('Error caught while calling pidusage');
console.error(err);
return cb(null, processes.map(function(pro) {
pro['monit'] = {
memory : 0,
cpu : 0
};
return pro
}))
}
if (!statistics) {
console.error('Statistics is not defined!')
return cb(null, processes.map(function(pro) {
pro['monit'] = {
memory : 0,
cpu : 0
};
return pro
}))
}
processes = processes.map(function(pro) {
if (filterBadProcess(pro) === false) {
pro['monit'] = {
memory : 0,
cpu : 0
};
return pro;
}
var pid = getProcessId(pro);
var stat = statistics[pid];
if (!stat) {
pro['monit'] = {
memory : 0,
cpu : 0
};
return pro;
}
pro['monit'] = {
memory: stat.memory,
cpu: Math.round(stat.cpu * 10) / 10
};
return pro;
});
cb(null, processes);
});
};
/**
* Description
* @method dumpProcessList
* @param {} cb
* @return
*/
God.dumpProcessList = function(cb) {
var process_list = [];
var apps = Utility.clone(God.getFormatedProcesses());
var that = this;
// Don't override the actual dump file if process list is empty
// unless user explicitely did `pm2 dump`.
// This often happens when PM2 crashed, we don't want to override
// the dump file with an empty list of process.
if (!apps[0]) {
debug('[PM2] Did not override dump file because list of processes is empty');
return cb(null, {success:true, process_list: process_list});
}
function fin(err) {
// try to fix issues with empty dump file
// like #3485
if (process_list.length === 0) {
// fix : if no dump file, no process, only module and after pm2 update
if (!fs.existsSync(cst.DUMP_FILE_PATH) && typeof that.clearDump === 'function') {
that.clearDump(function(){});
}
// if no process in list don't modify dump file
// process list should not be empty
return cb(null, {success:true, process_list: process_list});
}
// Back up dump file
try {
if (fs.existsSync(cst.DUMP_FILE_PATH)) {
fs.writeFileSync(cst.DUMP_BACKUP_FILE_PATH, fs.readFileSync(cst.DUMP_FILE_PATH));
}
} catch (e) {
console.error(e.stack || e);
}
// Overwrite dump file, delete if broken
try {
fs.writeFileSync(cst.DUMP_FILE_PATH, JSON.stringify(process_list));
} catch (e) {
console.error(e.stack || e);
try {
// try to backup file
if (fs.existsSync(cst.DUMP_BACKUP_FILE_PATH)) {
fs.writeFileSync(cst.DUMP_FILE_PATH, fs.readFileSync(cst.DUMP_BACKUP_FILE_PATH));
}
} catch (e) {
// don't keep broken file
fs.unlinkSync(cst.DUMP_FILE_PATH);
console.error(e.stack || e);
}
}
return cb(null, {success:true, process_list: process_list});
}
function saveProc(apps) {
if (!apps[0])
return fin(null);
delete apps[0].pm2_env.instances;
delete apps[0].pm2_env.pm_id;
// Do not dump modules
if (!apps[0].pm2_env.pmx_module)
process_list.push(apps[0].pm2_env);
apps.shift();
return saveProc(apps);
}
saveProc(apps);
};
/**
* Description
* @method ping
* @param {} env
* @param {} cb
* @return CallExpression
*/
God.ping = function(env, cb) {
return cb(null, {msg : 'pong'});
};
/**
* Description
* @method notifyKillPM2
*/
God.notifyKillPM2 = function() {
God.pm2_being_killed = true;
};
/**
* Duplicate a process
* @method duplicateProcessId
* @param {} id
* @param {} cb
* @return CallExpression
*/
God.duplicateProcessId = function(id, cb) {
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' id unknown'), {});
if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env)
return cb(God.logAndGenerateError('Error when getting proc || proc.pm2_env'), {});
var proc = Utility.clone(God.clusters_db[id].pm2_env);
delete proc.created_at;
delete proc.pm_id;
delete proc.unique_id;
// generate a new unique id for new process
proc.unique_id = Utility.generateUUID()
God.injectVariables(proc, function inject (_err, proc) {
return God.executeApp(Utility.clone(proc), function (err, clu) {
if (err) return cb(err);
God.notify('start', clu, true);
return cb(err, Utility.clone(clu));
});
});
};
/**
* Start a stopped process by ID
* @method startProcessId
* @param {} id
* @param {} cb
* @return CallExpression
*/
God.startProcessId = function(id, cb) {
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' id unknown'), {});
var proc = God.clusters_db[id];
if (proc.pm2_env.status == cst.ONLINE_STATUS)
return cb(God.logAndGenerateError('process already online'), {});
if (proc.pm2_env.status == cst.LAUNCHING_STATUS)
return cb(God.logAndGenerateError('process already started'), {});
if (proc.process && proc.process.pid)
return cb(God.logAndGenerateError('Process with pid ' + proc.process.pid + ' already exists'), {});
return God.executeApp(God.clusters_db[id].pm2_env, function(err, proc) {
return cb(err, Utility.clone(proc));
});
};
/**
* Stop a process and set it on state 'stopped'
* @method stopProcessId
* @param {} id
* @param {} cb
* @return Literal
*/
God.stopProcessId = function(id, cb) {
if (typeof id == 'object' && 'id' in id)
id = id.id;
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' : id unknown'), {});
var proc = God.clusters_db[id];
//clear time-out restart task
clearTimeout(proc.pm2_env.restart_task);
if (proc.pm2_env.status == cst.STOPPED_STATUS) {
proc.process.pid = 0;
return cb(null, God.getFormatedProcess(id));
}
// state == 'none' means that the process is not online yet
if (proc.state && proc.state === 'none')
return setTimeout(function() { God.stopProcessId(id, cb); }, 250);
console.log('Stopping app:%s id:%s', proc.pm2_env.name, proc.pm2_env.pm_id);
proc.pm2_env.status = cst.STOPPING_STATUS;
if (!proc.process.pid) {
console.error('app=%s id=%d does not have a pid', proc.pm2_env.name, proc.pm2_env.pm_id);
proc.pm2_env.status = cst.STOPPED_STATUS;
return cb(null, { error : true, message : 'could not kill process w/o pid'});
}
God.killProcess(proc.process.pid, proc.pm2_env, function(err) {
proc.pm2_env.status = cst.STOPPED_STATUS;
God.notify('exit', proc);
if (err && err.type && err.type === 'timeout') {
console.error('app=%s id=%d pid=%s could not be stopped',
proc.pm2_env.name,
proc.pm2_env.pm_id,
proc.process.pid);
proc.pm2_env.status = cst.ERRORED_STATUS;
return cb(null, God.getFormatedProcess(id));
}
if (proc.pm2_env.pm_id.toString().indexOf('_old_') !== 0) {
try {
fs.unlinkSync(proc.pm2_env.pm_pid_path);
} catch (e) {}
}
if (proc.pm2_env.axm_actions) proc.pm2_env.axm_actions = [];
if (proc.pm2_env.axm_monitor) proc.pm2_env.axm_monitor = {};
proc.process.pid = 0;
return cb(null, God.getFormatedProcess(id));
});
};
God.resetMetaProcessId = function(id, cb) {
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' id unknown'), {});
if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env)
return cb(God.logAndGenerateError('Error when getting proc || proc.pm2_env'), {});
God.clusters_db[id].pm2_env.created_at = Utility.getDate();
God.clusters_db[id].pm2_env.unstable_restarts = 0;
God.clusters_db[id].pm2_env.restart_time = 0;
return cb(null, God.getFormatedProcesses());
};
/**
* Delete a process by id
* It will stop it and remove it from the database
* @method deleteProcessId
* @param {} id
* @param {} cb
* @return Literal
*/
God.deleteProcessId = function(id, cb) {
God.deleteCron(id);
God.stopProcessId(id, function(err, proc) {
if (err) return cb(God.logAndGenerateError(err), {});
// ! transform to slow object
delete God.clusters_db[id];
if (Object.keys(God.clusters_db).length == 0)
God.next_id = 0;
return cb(null, proc);
});
return false;
};
/**
* Restart a process ID
* If the process is online it will not put it on state stopped
* but directly kill it and let God restart it
* @method restartProcessId
* @param {} id
* @param {} cb
* @return Literal
*/
God.restartProcessId = function(opts, cb) {
var id = opts.id;
var env = opts.env || {};
if (typeof(id) === 'undefined')
return cb(God.logAndGenerateError('opts.id not passed to restartProcessId', opts));
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError('God db process id unknown'), {});
var proc = God.clusters_db[id];
God.resetState(proc.pm2_env);
God.deleteCron(id);
/**
* Merge new application configuration on restart
* Same system in reloadProcessId and softReloadProcessId
*/
Utility.extend(proc.pm2_env.env, env);
Utility.extendExtraConfig(proc, opts);
if (God.pm2_being_killed) {
return cb(God.logAndGenerateError('[RestartProcessId] PM2 is being killed, stopping restart procedure...'));
}
if (proc.pm2_env.status === cst.ONLINE_STATUS || proc.pm2_env.status === cst.LAUNCHING_STATUS) {
God.stopProcessId(id, function(err) {
if (God.pm2_being_killed)
return cb(God.logAndGenerateError('[RestartProcessId] PM2 is being killed, stopping restart procedure...'));
proc.pm2_env.restart_time += 1;
return God.startProcessId(id, cb);
});
return false;
}
else {
debug('[restart] process not online, starting it');
return God.startProcessId(id, cb);
}
};
/**
* Restart all process by name
* @method restartProcessName
* @param {} name
* @param {} cb
* @return Literal
*/
God.restartProcessName = function(name, cb) {
var processes = God.findByName(name);
if (processes && processes.length === 0)
return cb(God.logAndGenerateError('Unknown process'), {});
eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) {
if (God.pm2_being_killed)
return next('[Watch] PM2 is being killed, stopping restart procedure...');
if (proc.pm2_env.status === cst.ONLINE_STATUS)
return God.restartProcessId({id:proc.pm2_env.pm_id}, next);
else if (proc.pm2_env.status !== cst.STOPPING_STATUS
&& proc.pm2_env.status !== cst.LAUNCHING_STATUS)
return God.startProcessId(proc.pm2_env.pm_id, next);
else
return next(util.format('[Watch] Process name %s is being stopped so I won\'t restart it', name));
}, function(err) {
if (err) return cb(God.logAndGenerateError(err));
return cb(null, God.getFormatedProcesses());
});
return false;
};
/**
* Send system signal to process id
* @method sendSignalToProcessId
* @param {} opts
* @param {} cb
* @return CallExpression
*/
God.sendSignalToProcessId = function(opts, cb) {
var id = opts.process_id;
var signal = opts.signal;
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' id unknown'), {});
var proc = God.clusters_db[id];
//God.notify('send signal ' + signal, proc, true);
try {
process.kill(God.clusters_db[id].process.pid, signal);
} catch(e) {
return cb(God.logAndGenerateError('Error when sending signal (signal unknown)'), {});
}
return cb(null, God.getFormatedProcesses());
};
/**
* Send system signal to all processes by name
* @method sendSignalToProcessName
* @param {} opts
* @param {} cb
* @return
*/
God.sendSignalToProcessName = function(opts, cb) {
var processes = God.findByName(opts.process_name);
var signal = opts.signal;
if (processes && processes.length === 0)
return cb(God.logAndGenerateError('Unknown process name'), {});
eachLimit(processes, cst.CONCURRENT_ACTIONS, function(proc, next) {
if (proc.pm2_env.status == cst.ONLINE_STATUS || proc.pm2_env.status == cst.LAUNCHING_STATUS) {
try {
process.kill(proc.process.pid, signal);
} catch(e) {
return next(e);
}
}
return setTimeout(next, 200);
}, function(err) {
if (err) return cb(God.logAndGenerateError(err), {});
return cb(null, God.getFormatedProcesses());
});
};
/**
* Stop watching daemon
* @method stopWatch
* @param {} method
* @param {} value
* @param {} fn
* @return
*/
God.stopWatch = function(method, value, fn) {
var env = null;
if (method == 'stopAll' || method == 'deleteAll') {
var processes = God.getFormatedProcesses();
processes.forEach(function(proc) {
God.clusters_db[proc.pm_id].pm2_env.watch = false;
God.watch.disable(proc.pm2_env);
});
} else {
if (method.indexOf('ProcessId') !== -1) {
env = God.clusters_db[value];
} else if (method.indexOf('ProcessName') !== -1) {
env = God.clusters_db[God.findByName(value)];
}
if (env) {
God.watch.disable(env.pm2_env);
env.pm2_env.watch = false;
}
}
return fn(null, {success:true});
};
/**
* Toggle watching daemon
* @method toggleWatch
* @param {String} method
* @param {Object} application environment, should include id
* @param {Function} callback
*/
God.toggleWatch = function(method, value, fn) {
var env = null;
if (method == 'restartProcessId') {
env = God.clusters_db[value.id];
} else if(method == 'restartProcessName') {
env = God.clusters_db[God.findByName(value)];
}
if (env) {
env.pm2_env.watch = !env.pm2_env.watch;
if (env.pm2_env.watch)
God.watch.enable(env.pm2_env);
else
God.watch.disable(env.pm2_env);
}
return fn(null, {success:true});
};
/**
* Start Watch
* @method startWatch
* @param {String} method
* @param {Object} application environment, should include id
* @param {Function} callback
*/
God.startWatch = function(method, value, fn) {
var env = null;
if (method == 'restartProcessId') {
env = God.clusters_db[value.id];
} else if(method == 'restartProcessName') {
env = God.clusters_db[God.findByName(value)];
}
if (env) {
if (env.pm2_env.watch)
return fn(null, {success:true, notrestarted:true});
God.watch.enable(env.pm2_env);
//env.pm2_env.env.watch = true;
env.pm2_env.watch = true;
}
return fn(null, {success:true});
};
/**
* Description
* @method reloadLogs
* @param {} opts
* @param {} cb
* @return CallExpression
*/
God.reloadLogs = function(opts, cb) {
console.log('Reloading logs...');
var processIds = Object.keys(God.clusters_db);
processIds.forEach(function (id) {
var cluster = God.clusters_db[id];
console.log('Reloading logs for process id %d', id);
if (cluster && cluster.pm2_env) {
// Cluster mode
if (cluster.send && cluster.pm2_env.exec_mode == 'cluster_mode') {
try {
cluster.send({
type:'log:reload'
});
} catch(e) {
console.error(e.message || e);
}
}
// Fork mode
else if (cluster._reloadLogs) {
cluster._reloadLogs(function(err) {
if (err) God.logAndGenerateError(err);
});
}
}
});
return cb(null, {});
};
/**
* Send Line To Stdin
* @method sendLineToStdin
* @param Object packet
* @param String pm_id Process ID
* @param String line Line to send to process stdin
*/
God.sendLineToStdin = function(packet, cb) {
if (typeof(packet.pm_id) == 'undefined' || !packet.line)
return cb(God.logAndGenerateError('pm_id or line field missing'), {});
var pm_id = packet.pm_id;
var line = packet.line;
var proc = God.clusters_db[pm_id];
if (!proc)
return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> unknown.'), {});
if (proc.pm2_env.exec_mode == 'cluster_mode')
return cb(God.logAndGenerateError('Cannot send line to processes in cluster mode'), {});
if (proc.pm2_env.status != cst.ONLINE_STATUS && proc.pm2_env.status != cst.LAUNCHING_STATUS)
return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> offline.'), {});
try {
proc.stdin.write(line, function() {
return cb(null, {
pm_id : pm_id,
line : line
});
});
} catch(e) {
return cb(God.logAndGenerateError(e), {});
}
}
/**
* @param {object} packet
* @param {function} cb
*/
God.sendDataToProcessId = function(packet, cb) {
if (typeof(packet.id) == 'undefined' ||
typeof(packet.data) == 'undefined' ||
!packet.topic)
return cb(God.logAndGenerateError('ID, DATA or TOPIC field is missing'), {});
var pm_id = packet.id;
var data = packet.data;
var proc = God.clusters_db[pm_id];
if (!proc)
return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> unknown.'), {});
if (proc.pm2_env.status != cst.ONLINE_STATUS && proc.pm2_env.status != cst.LAUNCHING_STATUS)
return cb(God.logAndGenerateError('Process with ID <' + pm_id + '> offline.'), {});
try {
proc.send(packet);
}
catch(e) {
return cb(God.logAndGenerateError(e), {});
}
return cb(null, {
success: true,
data : packet
});
};
/**
* Send Message to Process by id or name
* @method msgProcess
* @param {} cmd
* @param {} cb
* @return Literal
*/
God.msgProcess = function(cmd, cb) {
if ('id' in cmd) {
var id = cmd.id;
if (!(id in God.clusters_db))
return cb(God.logAndGenerateError(id + ' id unknown'), {});
var proc = God.clusters_db[id];
var action_exist = false;
proc.pm2_env.axm_actions.forEach(function(action) {
if (action.action_name == cmd.msg) {
action_exist = true;
// Reset output buffer
action.output = [];
}
});
if (action_exist == false) {
return cb(God.logAndGenerateError('Action doesn\'t exist ' + cmd.msg + ' for ' + proc.pm2_env.name), {});
}
if (proc.pm2_env.status == cst.ONLINE_STATUS || proc.pm2_env.status == cst.LAUNCHING_STATUS) {
/*
* Send message
*/
if (cmd.opts == null && !cmd.uuid)
proc.send(cmd.msg);
else
proc.send(cmd);
return cb(null, { process_count : 1, success : true });
}
else
return cb(God.logAndGenerateError(id + ' : id offline'), {});
}
else if ('name' in cmd) {
/*
* As names are not unique in case of cluster, this
* will send msg to all process matching 'name'
*/
var name = cmd.name;
var arr = Object.keys(God.clusters_db);
var sent = 0;
(function ex(arr) {
if (arr[0] == null || !arr) {
return cb(null, {
process_count : sent,
success : true
});
}
var id = arr[0];
if (!God.clusters_db[id] || !God.clusters_db[id].pm2_env) {
arr.shift();
return ex(arr);
}
var proc_env = God.clusters_db[id].pm2_env;
const isActionAvailable = proc_env.axm_actions.find(action => action.action_name === cmd.msg) !== undefined
// if action doesn't exist for this app
// try with the next one
if (isActionAvailable === false) {
arr.shift();
return ex(arr);
}
if ((p.basename(proc_env.pm_exec_path) == name ||
proc_env.name == name ||
proc_env.namespace == name ||
name == 'all') &&
(proc_env.status == cst.ONLINE_STATUS ||
proc_env.status == cst.LAUNCHING_STATUS)) {
proc_env.axm_actions.forEach(function(action) {
if (action.action_name == cmd.msg) {
action_exist = true;
}
});
if (action_exist == false || proc_env.axm_actions.length == 0) {
arr.shift();
return ex(arr);
}
if (cmd.opts == null)
God.clusters_db[id].send(cmd.msg);
else
God.clusters_db[id].send(cmd);
sent++;
arr.shift();
return ex(arr);
}
else {
arr.shift();
return ex(arr);
}
return false;
})(arr);
}
else return cb(God.logAndGenerateError('method requires name or id field'), {});
return false;
};
/**
* Description
* @method getVersion
* @param {} env
* @param {} cb
* @return CallExpression
*/
God.getVersion = function(env, cb) {
process.nextTick(function() {
return cb(null, pkg.version);
});
};
God.monitor = function Monitor(pm_id, cb) {
if (!God.clusters_db[pm_id] || !God.clusters_db[pm_id].pm2_env)
return cb(new Error('Unknown pm_id'));
God.clusters_db[pm_id].pm2_env._km_monitored = true;
return cb(null, { success : true, pm_id : pm_id });
}
God.unmonitor = function Monitor(pm_id, cb) {
if (!God.clusters_db[pm_id] || !God.clusters_db[pm_id].pm2_env)
return cb(new Error('Unknown pm_id'));
God.clusters_db[pm_id].pm2_env._km_monitored = false;
return cb(null, { success : true, pm_id : pm_id });
}
God.getReport = function(arg, cb) {
var report = {
pm2_version : pkg.version,
node_version : 'N/A',
node_path : process.env['_'] || 'not found',
argv0 : process.argv0,
argv : process.argv,
user : process.env.USER,
uid : (cst.IS_WINDOWS === false && process.geteuid) ? process.geteuid() : 'N/A',
gid : (cst.IS_WINDOWS === false && process.getegid) ? process.getegid() : 'N/A',
env : process.env,
managed_apps : Object.keys(God.clusters_db).length,
started_at : God.started_at
};
if (process.versions && process.versions.node) {
report.node_version = process.versions.node;
}
process.nextTick(function() {
return cb(null, report);
});
};
};
function filterBadProcess(pro) {
if (pro.pm2_env.status !== cst.ONLINE_STATUS) {
return false;
}
if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) {
if (isNaN(pro.pm2_env.axm_options.pid)) {
return false;
}
}
return true;
}
function getProcessId(pro) {
var pid = pro.pid
if (pro.pm2_env.axm_options && pro.pm2_env.axm_options.pid) {
pid = pro.pm2_env.axm_options.pid;
}
return pid
}

97
api.hyungi.net/node_modules/pm2/lib/God/ClusterMode.js generated vendored Normal file
View File

@@ -0,0 +1,97 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
/**
* @file Cluster execution functions related
* @author Alexandre Strzelewicz <as@unitech.io>
* @project PM2
*/
var cluster = require('cluster');
var Utility = require('../Utility.js');
var pkg = require('../../package.json');
/**
* Description
* @method exports
* @param {} God
* @return
*/
module.exports = function ClusterMode(God) {
/**
* For Node apps - Cluster mode
* It will wrap the code and enable load-balancing mode
* @method nodeApp
* @param {} env_copy
* @param {} cb
* @return Literal
*/
God.nodeApp = function nodeApp(env_copy, cb){
var clu = null;
console.log(`App [${env_copy.name}:${env_copy.pm_id}] starting in -cluster mode-`)
if (env_copy.node_args && Array.isArray(env_copy.node_args)) {
cluster.settings.execArgv = env_copy.node_args;
}
env_copy._pm2_version = pkg.version;
try {
// node.js cluster clients can not receive deep-level objects or arrays in the forked process, e.g.:
// { "args": ["foo", "bar"], "env": { "foo1": "bar1" }} will be parsed to
// { "args": "foo, bar", "env": "[object Object]"}
// So we passing a stringified JSON here.
clu = cluster.fork({pm2_env: JSON.stringify(env_copy), windowsHide: true});
} catch(e) {
God.logAndGenerateError(e);
return cb(e);
}
clu.pm2_env = env_copy;
/**
* Broadcast message to God
*/
clu.on('message', function cluMessage(msg) {
/*********************************
* If you edit this function
* Do the same in ForkMode.js !
*********************************/
if (msg.data && msg.type) {
return God.bus.emit(msg.type ? msg.type : 'process:msg', {
at : Utility.getDate(),
data : msg.data,
process : {
pm_id : clu.pm2_env.pm_id,
name : clu.pm2_env.name,
rev : (clu.pm2_env.versioning && clu.pm2_env.versioning.revision) ? clu.pm2_env.versioning.revision : null,
namespace : clu.pm2_env.namespace
}
});
}
else {
if (typeof msg == 'object' && 'node_version' in msg) {
clu.pm2_env.node_version = msg.node_version;
return false;
}
return God.bus.emit('process:msg', {
at : Utility.getDate(),
raw : msg,
process : {
pm_id : clu.pm2_env.pm_id,
name : clu.pm2_env.name,
namespace : clu.pm2_env.namespace
}
});
}
});
return cb(null, clu);
};
};

293
api.hyungi.net/node_modules/pm2/lib/God/ForkMode.js generated vendored Normal file
View File

@@ -0,0 +1,293 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
/**
* @file Fork execution related functions
* @author Alexandre Strzelewicz <as@unitech.io>
* @project PM2
*/
var log = require('debug')('pm2:fork_mode');
var fs = require('fs');
var Utility = require('../Utility.js');
var path = require('path');
var dayjs = require('dayjs');
var semver = require('semver')
/**
* Description
* @method exports
* @param {} God
* @return
*/
module.exports = function ForkMode(God) {
/**
* For all apps - FORK MODE
* fork the app
* @method forkMode
* @param {} pm2_env
* @param {} cb
* @return
*/
God.forkMode = function forkMode(pm2_env, cb) {
var command = '';
var args = [];
console.log(`App [${pm2_env.name}:${pm2_env.pm_id}] starting in -fork mode-`)
var spawn = require('child_process').spawn;
var interpreter = pm2_env.exec_interpreter || 'node';
var pidFile = pm2_env.pm_pid_path;
if (interpreter !== 'none') {
command = interpreter;
if (pm2_env.node_args && Array.isArray(pm2_env.node_args)) {
args = args.concat(pm2_env.node_args);
}
// Deprecated - to remove at some point
if (process.env.PM2_NODE_OPTIONS) {
args = args.concat(process.env.PM2_NODE_OPTIONS.split(' '));
}
if (interpreter === 'node' || RegExp('node$').test(interpreter)) {
args.push(path.resolve(path.dirname(module.filename), '..', 'ProcessContainerFork.js'));
}
else
args.push(pm2_env.pm_exec_path);
}
else {
command = pm2_env.pm_exec_path;
args = [ ];
}
if (pm2_env.args) {
args = args.concat(pm2_env.args);
}
// piping stream o file
var stds = {
out: pm2_env.pm_out_log_path,
err: pm2_env.pm_err_log_path
};
// entire log std if necessary.
if ('pm_log_path' in pm2_env){
stds.std = pm2_env.pm_log_path;
}
log("stds: %j", stds);
Utility.startLogging(stds, function(err, result) {
if (err) {
God.logAndGenerateError(err);
return cb(err);
};
try {
var options = {
env : pm2_env,
detached : true,
cwd : pm2_env.pm_cwd || process.cwd(),
stdio : ['pipe', 'pipe', 'pipe', 'ipc'] //Same as fork() in node core
}
if (typeof(pm2_env.windowsHide) === "boolean") {
options.windowsHide = pm2_env.windowsHide;
} else {
options.windowsHide = true;
}
if (pm2_env.uid) {
options.uid = pm2_env.uid
}
if (pm2_env.gid) {
options.gid = pm2_env.gid
}
var cspr = spawn(command, args, options);
} catch(e) {
God.logAndGenerateError(e);
return cb(e);
}
if (!cspr || !cspr.stderr || !cspr.stdout) {
var fatalError = new Error('Process could not be forked properly, check your system health')
God.logAndGenerateError(fatalError);
return cb(fatalError);
}
cspr.process = {};
cspr.process.pid = cspr.pid;
cspr.pm2_env = pm2_env;
function transformLogToJson(pm2_env, type, data) {
return JSON.stringify({
message : data.toString(),
timestamp : pm2_env.log_date_format ? dayjs().format(pm2_env.log_date_format) : new Date().toISOString(),
type : type,
process_id : cspr.pm2_env.pm_id,
app_name : cspr.pm2_env.name
}) + '\n'
}
function prefixLogWithDate(pm2_env, data) {
var log_data = []
log_data = data.toString().split('\n')
if (log_data.length > 1)
log_data.pop()
log_data = log_data.map(line => `${dayjs().format(pm2_env.log_date_format)}: ${line}\n`)
log_data = log_data.join('')
return log_data
}
cspr.stderr.on('data', function forkErrData(data) {
var log_data = null;
// via --out /dev/null --err /dev/null
if (pm2_env.disable_logs === true) return false;
if (pm2_env.log_type && pm2_env.log_type === 'json')
log_data = transformLogToJson(pm2_env, 'err', data)
else if (pm2_env.log_date_format)
log_data = prefixLogWithDate(pm2_env, data)
else
log_data = data.toString();
God.bus.emit('log:err', {
process : {
pm_id : cspr.pm2_env.pm_id,
name : cspr.pm2_env.name,
rev : (cspr.pm2_env.versioning && cspr.pm2_env.versioning.revision) ? cspr.pm2_env.versioning.revision : null,
namespace : cspr.pm2_env.namespace
},
at : Utility.getDate(),
data : log_data
});
if (Utility.checkPathIsNull(pm2_env.pm_err_log_path) &&
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path))) {
return false;
}
stds.std && stds.std.write && stds.std.write(log_data);
stds.err && stds.err.write && stds.err.write(log_data);
});
cspr.stdout.on('data', function forkOutData(data) {
var log_data = null;
if (pm2_env.disable_logs === true)
return false;
if (pm2_env.log_type && pm2_env.log_type === 'json')
log_data = transformLogToJson(pm2_env, 'out', data)
else if (pm2_env.log_date_format)
log_data = prefixLogWithDate(pm2_env, data)
else
log_data = data.toString()
God.bus.emit('log:out', {
process : {
pm_id : cspr.pm2_env.pm_id,
name : cspr.pm2_env.name,
rev : (cspr.pm2_env.versioning && cspr.pm2_env.versioning.revision) ? cspr.pm2_env.versioning.revision : null,
namespace : cspr.pm2_env.namespace
},
at : Utility.getDate(),
data : log_data
});
if (Utility.checkPathIsNull(pm2_env.pm_out_log_path) &&
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
return false;
stds.std && stds.std.write && stds.std.write(log_data);
stds.out && stds.out.write && stds.out.write(log_data);
});
/**
* Broadcast message to God
*/
cspr.on('message', function forkMessage(msg) {
/*********************************
* If you edit this function
* Do the same in ClusterMode.js !
*********************************/
if (msg.data && msg.type) {
process.nextTick(function() {
return God.bus.emit(msg.type ? msg.type : 'process:msg', {
at : Utility.getDate(),
data : msg.data,
process : {
pm_id : cspr.pm2_env.pm_id,
name : cspr.pm2_env.name,
versioning : cspr.pm2_env.versioning,
namespace : cspr.pm2_env.namespace
}
});
});
}
else {
if (typeof msg == 'object' && 'node_version' in msg) {
cspr.pm2_env.node_version = msg.node_version;
return false;
}
return God.bus.emit('process:msg', {
at : Utility.getDate(),
raw : msg,
process : {
pm_id : cspr.pm2_env.pm_id,
name : cspr.pm2_env.name,
namespace : cspr.pm2_env.namespace
}
});
}
});
try {
var pid = cspr.pid
if (typeof(pid) !== 'undefined')
fs.writeFileSync(pidFile, pid.toString());
} catch (e) {
console.error(e.stack || e);
}
cspr.once('exit', function forkClose(status) {
try {
for(var k in stds){
if (stds[k] && stds[k].destroy) stds[k].destroy();
else if (stds[k] && stds[k].end) stds[k].end();
else if (stds[k] && stds[k].close) stds[k].close();
stds[k] = stds[k]._file;
}
} catch(e) { God.logAndGenerateError(e);}
});
cspr._reloadLogs = function(cb) {
try {
for (var k in stds){
if (stds[k] && stds[k].destroy) stds[k].destroy();
else if (stds[k] && stds[k].end) stds[k].end();
else if (stds[k] && stds[k].close) stds[k].close();
stds[k] = stds[k]._file;
}
} catch(e) { God.logAndGenerateError(e);}
//cspr.removeAllListeners();
Utility.startLogging(stds, cb);
};
cspr.unref();
return cb(null, cspr);
});
};
};

265
api.hyungi.net/node_modules/pm2/lib/God/Methods.js generated vendored Normal file
View File

@@ -0,0 +1,265 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
/**
* @file Utilities for PM2
* @author Alexandre Strzelewicz <as@unitech.io>
* @project PM2
*/
var p = require('path');
var treekill = require('../TreeKill');
var cst = require('../../constants.js');
/**
* Description
* @method exports
* @param {} God
* @return
*/
module.exports = function(God) {
/**
* Description
* @method logAndGenerateError
* @param {} err
* @return NewExpression
*/
God.logAndGenerateError = function(err) {
// Is an Error object
if (err instanceof Error) {
console.trace(err);
return err;
}
// Is a JSON or simple string
console.error(err);
return new Error(err);
};
/**
* Utility functions
* @method getProcesses
* @return MemberExpression
*/
God.getProcesses = function() {
return God.clusters_db;
};
God.getFormatedProcess = function getFormatedProcesses(id) {
if (God.clusters_db[id])
return {
pid : God.clusters_db[id].process.pid,
name : God.clusters_db[id].pm2_env.name,
pm2_env : God.clusters_db[id].pm2_env,
pm_id : God.clusters_db[id].pm2_env.pm_id
};
return {};
};
/**
* Get formated processes
* @method getFormatedProcesses
* @return {Array} formated processes
*/
God.getFormatedProcesses = function getFormatedProcesses() {
var keys = Object.keys(God.clusters_db);
var arr = new Array();
var kl = keys.length;
for (var i = 0; i < kl; i++) {
var key = keys[i];
if (!God.clusters_db[key]) continue;
// Avoid _old type pm_ids
if (isNaN(God.clusters_db[key].pm2_env.pm_id)) continue;
arr.push({
pid : God.clusters_db[key].process.pid,
name : God.clusters_db[key].pm2_env.name,
pm2_env : God.clusters_db[key].pm2_env,
pm_id : God.clusters_db[key].pm2_env.pm_id
})
}
return arr;
};
/**
* Description
* @method findProcessById
* @param {} id
* @return ConditionalExpression
*/
God.findProcessById = function findProcessById(id) {
return God.clusters_db[id] ? God.clusters_db[id] : null;
};
/**
* Description
* @method findByName
* @param {} name
* @return arr
*/
God.findByName = function(name) {
var db = God.clusters_db;
var arr = [];
if (name == 'all') {
for (var key in db) {
// Avoid _old_proc process style
if (typeof(God.clusters_db[key].pm2_env.pm_id) === 'number')
arr.push(db[key]);
}
return arr;
}
for (var key in db) {
if (God.clusters_db[key].pm2_env.name == name ||
God.clusters_db[key].pm2_env.pm_exec_path == p.resolve(name)) {
arr.push(db[key]);
}
}
return arr;
};
/**
* Check if a process is alive in system processes
* Return TRUE if process online
* @method checkProcess
* @param {} pid
* @return
*/
God.checkProcess = function(pid) {
if (!pid) return false;
try {
// Sending 0 signal do not kill the process
process.kill(pid, 0);
return true;
}
catch (err) {
return false;
}
};
/**
* Description
* @method processIsDead
* @param {} pid
* @param {} cb
* @return Literal
*/
God.processIsDead = function(pid, pm2_env, cb, sigkill) {
if (!pid) return cb({type : 'param:missing', msg : 'no pid passed'});
var timeout = null;
var kill_timeout = (pm2_env && pm2_env.kill_timeout) ? pm2_env.kill_timeout : cst.KILL_TIMEOUT;
var mode = pm2_env.exec_mode;
var timer = setInterval(function() {
if (God.checkProcess(pid) === false) {
console.log('pid=%d msg=process killed', pid);
clearTimeout(timeout);
clearInterval(timer);
return cb(null, true);
}
console.log('pid=%d msg=failed to kill - retrying in %dms', pid, pm2_env.kill_retry_time);
return false;
}, pm2_env.kill_retry_time);
timeout = setTimeout(function() {
clearInterval(timer);
if (sigkill) {
console.log('Process with pid %d could not be killed', pid);
return cb({type : 'timeout', msg : 'timeout'});
}
else {
console.log('Process with pid %d still alive after %sms, sending it SIGKILL now...', pid, kill_timeout);
if (pm2_env.treekill !== true) {
try {
process.kill(parseInt(pid), 'SIGKILL');
} catch(e) {
console.error('[SimpleKill][SIGKILL] %s pid can not be killed', pid, e.stack, e.message);
}
return God.processIsDead(pid, pm2_env, cb, true);
}
else {
treekill(parseInt(pid), 'SIGKILL', function(err) {
return God.processIsDead(pid, pm2_env, cb, true);
});
}
}
}, kill_timeout);
return false;
};
/**
* Description
* @method killProcess
* @param int pid
* @param Object pm2_env
* @param function cb
* @return CallExpression
*/
God.killProcess = function(pid, pm2_env, cb) {
if (!pid) return cb({msg : 'no pid passed or null'});
if (typeof(pm2_env.pm_id) === 'number' &&
(cst.KILL_USE_MESSAGE || pm2_env.shutdown_with_message == true)) {
var proc = God.clusters_db[pm2_env.pm_id];
if (proc && proc.send) {
try {
proc.send('shutdown');
} catch (e) {
console.error(`[AppKill] Cannot send "shutdown" message to ${pid}`)
console.error(e.stack, e.message)
}
return God.processIsDead(pid, pm2_env, cb);
}
else {
console.log(`[AppKill] ${pid} pid cannot be notified with send()`)
}
}
if (pm2_env.treekill !== true) {
try {
process.kill(parseInt(pid), cst.KILL_SIGNAL);
} catch(e) {
console.error('[SimpleKill] %s pid can not be killed', pid, e.stack, e.message);
}
return God.processIsDead(pid, pm2_env, cb);
}
else {
treekill(parseInt(pid), cst.KILL_SIGNAL, function(err) {
return God.processIsDead(pid, pm2_env, cb);
});
}
};
/**
* Description
* @method getNewId
* @return UpdateExpression
*/
God.getNewId = function() {
return God.next_id++;
};
/**
* When a process is restarted or reloaded reset fields
* to monitor unstable starts
* @method resetState
* @param {} pm2_env
* @return
*/
God.resetState = function(pm2_env) {
pm2_env.created_at = Date.now();
pm2_env.unstable_restarts = 0;
pm2_env.prev_restart_delay = 0;
};
};

240
api.hyungi.net/node_modules/pm2/lib/God/Reload.js generated vendored Normal file
View File

@@ -0,0 +1,240 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
'use strict';
/**
* @file Reload functions related
* @author Alexandre Strzelewicz <as@unitech.io>
* @project PM2
*/
var cst = require('../../constants.js');
var Utility = require('../Utility.js');
/**
* softReload will wait permission from process to exit
* @method softReload
* @param {} God
* @param {} id
* @param {} cb
* @return Literal
*/
function softReload(God, id, cb) {
var t_key = '_old_' + id;
// Move old worker to tmp id
God.clusters_db[t_key] = God.clusters_db[id];
delete God.clusters_db[id];
var old_worker = God.clusters_db[t_key];
// Deep copy
var new_env = Utility.clone(old_worker.pm2_env);
// Reset created_at and unstable_restarts
God.resetState(new_env);
new_env.restart_time += 1;
old_worker.pm2_env.pm_id = t_key;
old_worker.pm_id = t_key;
God.executeApp(new_env, function(err, new_worker) {
if (err) return cb(err);
var timer = null;
var onListen = function () {
clearTimeout(timer);
softCleanDeleteProcess();
console.log('-softReload- New worker listening');
};
// Bind to know when the new process is up
new_worker.once('listening', onListen);
timer = setTimeout(function() {
new_worker.removeListener('listening', onListen);
softCleanDeleteProcess();
}, new_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
// Remove old worker properly
var softCleanDeleteProcess = function () {
var cleanUp = function () {
clearTimeout(timer);
console.log('-softReload- Old worker disconnected');
return God.deleteProcessId(t_key, cb);
};
old_worker.once('disconnect', cleanUp);
try {
if (old_worker.state != 'dead' && old_worker.state != 'disconnected')
old_worker.send && old_worker.send('shutdown');
else {
clearTimeout(timer);
console.error('Worker %d is already disconnected', old_worker.pm2_env.pm_id);
return God.deleteProcessId(t_key, cb);
}
} catch(e) {
clearTimeout(timer);
console.error('Worker %d is already disconnected', old_worker.pm2_env.pm_id);
return God.deleteProcessId(t_key, cb);
}
timer = setTimeout(function () {
old_worker.removeListener('disconnect', cleanUp);
return God.deleteProcessId(t_key, cb);
}, cst.GRACEFUL_TIMEOUT);
return false;
};
return false;
});
return false;
};
/**
* hardReload will reload without waiting permission from process
* @method hardReload
* @param {} God
* @param {} id
* @param {} cb
* @return Literal
*/
function hardReload(God, id, wait_msg, cb) {
var t_key = '_old_' + id;
// Move old worker to tmp id
God.clusters_db[t_key] = God.clusters_db[id];
delete God.clusters_db[id];
var old_worker = God.clusters_db[t_key];
// Deep copy
var new_env = Utility.clone(old_worker.pm2_env);
new_env.restart_time += 1;
// Reset created_at and unstable_restarts
God.resetState(new_env);
old_worker.pm2_env.pm_id = t_key;
old_worker.pm_id = t_key;
var timer = null;
var readySignalSent = false;
var onListen = function () {
clearTimeout(timer);
readySignalSent = true;
console.log('-reload- New worker listening');
return God.deleteProcessId(t_key, cb);
};
var listener = function (packet) {
if (packet.raw === 'ready' &&
packet.process.name === old_worker.pm2_env.name &&
packet.process.pm_id === id) {
God.bus.removeListener('process:msg', listener);
return onListen();
}
};
if (wait_msg !== 'listening') {
God.bus.on('process:msg', listener);
}
God.executeApp(new_env, function(err, new_worker) {
if (err) return cb(err);
// Bind to know when the new process is up
if (wait_msg === 'listening') {
new_worker.once('listening', onListen);
}
timer = setTimeout(function() {
if (readySignalSent) {
return;
}
if (wait_msg === 'listening')
new_worker.removeListener(wait_msg, onListen);
else
God.bus.removeListener('process:msg', listener);
return God.deleteProcessId(t_key, cb);
}, new_env.listen_timeout || cst.GRACEFUL_LISTEN_TIMEOUT);
return false;
});
return false;
};
/**
* Description
* @method exports
* @param {} God
* @return
*/
module.exports = function(God) {
/**
* Reload
* @method softReloadProcessId
* @param {} id
* @param {} cb
* @return CallExpression
*/
God.softReloadProcessId = function(opts, cb) {
var id = opts.id;
var env = opts.env || {};
if (!(id in God.clusters_db))
return cb(new Error(`pm_id ${id} not available in ${id}`));
if (God.clusters_db[id].pm2_env.status == cst.ONLINE_STATUS &&
God.clusters_db[id].pm2_env.exec_mode == 'cluster_mode' &&
!God.clusters_db[id].pm2_env.wait_ready) {
Utility.extend(God.clusters_db[id].pm2_env.env, opts.env);
Utility.extendExtraConfig(God.clusters_db[id], opts);
return softReload(God, id, cb);
}
else {
console.log('Process %s in a stopped status, starting it', id);
return God.restartProcessId(opts, cb);
}
};
/**
* Reload
* @method reloadProcessId
* @param {} id
* @param {} cb
* @return CallExpression
*/
God.reloadProcessId = function(opts, cb) {
var id = opts.id;
var env = opts.env || {};
if (!(id in God.clusters_db))
return cb(new Error('PM2 ID unknown'));
if (God.clusters_db[id].pm2_env.status == cst.ONLINE_STATUS &&
God.clusters_db[id].pm2_env.exec_mode == 'cluster_mode') {
Utility.extend(God.clusters_db[id].pm2_env.env, opts.env);
Utility.extendExtraConfig(God.clusters_db[id], opts);
var wait_msg = God.clusters_db[id].pm2_env.wait_ready ? 'ready' : 'listening';
return hardReload(God, id, wait_msg, cb);
}
else {
console.log('Process %s in a stopped status, starting it', id);
return God.restartProcessId(opts, cb);
}
};
};

76
api.hyungi.net/node_modules/pm2/lib/HttpInterface.js generated vendored Normal file
View File

@@ -0,0 +1,76 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var http = require('http');
var os = require('os');
var pm2 = require('../index.js');
var urlT = require('url');
var cst = require('../constants.js');
// Default, attach to default local PM2
pm2.connect(function() {
startWebServer(pm2);
});
function startWebServer(pm2) {
http.createServer(function (req, res) {
// Add CORS headers to allow browsers to fetch data directly
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader('Access-Control-Allow-Headers', 'Cache-Control, Pragma, Origin, Authorization, Content-Type, X-Requested-With');
res.setHeader('Access-Control-Allow-Methods', 'GET');
// We always send json
res.setHeader('Content-Type','application/json');
var path = urlT.parse(req.url).pathname;
if (path == '/') {
// Main monit route
pm2.list(function(err, list) {
if (err) {
return res.send(err);
}
var data = {
system_info: { hostname: os.hostname(),
uptime: os.uptime()
},
monit: { loadavg: os.loadavg(),
total_mem: os.totalmem(),
free_mem: os.freemem(),
cpu: os.cpus(),
interfaces: os.networkInterfaces()
},
processes: list
};
if (cst.WEB_STRIP_ENV_VARS === true) {
for (var i = data.processes.length - 1; i >= 0; i--) {
var proc = data.processes[i];
// Strip important environment variables
if (typeof proc.pm2_env === 'undefined' && typeof proc.pm2_env.env === 'undefined') return;
delete proc.pm2_env.env;
}
}
res.statusCode = 200;
res.write(JSON.stringify(data));
return res.end();
})
}
else {
// 404
res.statusCode = 404;
res.write(JSON.stringify({err : '404'}));
return res.end();
}
}).listen(process.env.PM2_WEB_PORT || cst.WEB_PORT, cst.WEB_IPADDR, function() {
console.log('Web interface listening on %s:%s', cst.WEB_IPADDR, cst.WEB_PORT);
});
}

315
api.hyungi.net/node_modules/pm2/lib/ProcessContainer.js generated vendored Normal file
View File

@@ -0,0 +1,315 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*
* This file wrap target application
* - redirect stdin, stderr to bus + log files
* - rename process
* - pid
*/
var p = require('path');
var cst = require('../constants');
var Utility = require('./Utility.js');
var ProcessUtils = require('./ProcessUtils');
var Url = require('url');
// Load all env-vars from master.
var pm2_env = JSON.parse(process.env.pm2_env);
for(var k in pm2_env) {
process.env[k] = pm2_env[k];
}
// Rename process
process.title = process.env.PROCESS_TITLE || 'node ' + pm2_env.pm_exec_path;
delete process.env.pm2_env;
/**
* Main entrance to wrap the desired code
*/
(function ProcessContainer() {
var fs = require('fs');
ProcessUtils.injectModules()
var stdFile = pm2_env.pm_log_path;
var outFile = pm2_env.pm_out_log_path;
var errFile = pm2_env.pm_err_log_path;
var pidFile = pm2_env.pm_pid_path;
var script = pm2_env.pm_exec_path;
var original_send = process.send;
if (typeof(process.env.source_map_support) != 'undefined' &&
process.env.source_map_support !== 'false') {
require('source-map-support').install();
}
process.send = function() {
if (process.connected)
original_send.apply(this, arguments);
};
//send node version
if (process.versions && process.versions.node) {
process.send({
'node_version': process.versions.node
});
}
if (cst.MODIFY_REQUIRE)
require.main.filename = pm2_env.pm_exec_path;
// Resets global paths for require()
require('module')._initPaths();
try {
var pid = process.pid
if (typeof(pid) !== 'undefined')
fs.writeFileSync(pidFile, process.pid.toString());
} catch (e) {
console.error(e.stack || e);
}
// Add args to process if args specified on start
if (process.env.args != null)
process.argv = process.argv.concat(pm2_env.args);
// stdio, including: out, err and entire (both out and err if necessary).
var stds = {
out: outFile,
err: errFile
};
stdFile && (stds.std = stdFile);
// uid/gid management
if (pm2_env.uid || pm2_env.gid) {
try {
if (process.env.gid)
process.setgid(pm2_env.gid);
if (pm2_env.uid)
process.setuid(pm2_env.uid);
} catch(e) {
setTimeout(function() {
console.error('%s on call %s', e.message, e.syscall);
console.error('%s is not accessible', pm2_env.uid);
return process.exit(1);
}, 100);
}
}
exec(script, stds);
})();
/**
* Description
* @method exec
* @param {} script
* @param {} stds
* @return
*/
function exec(script, stds) {
if (p.extname(script) == '.coffee') {
try {
require('coffee-script/register');
} catch (e) {
console.error('Failed to load CoffeeScript interpreter:', e.message || e);
}
}
if (p.extname(script) == '.ls') {
try {
require('livescript');
} catch (e) {
console.error('Failed to load LiveScript interpreter:', e.message || e);
}
}
if (p.extname(script) == '.ts' || p.extname(script) == '.tsx') {
try {
require('ts-node/register');
} catch (e) {
console.error('Failed to load Typescript interpreter:', e.message || e);
}
}
process.on('message', function (msg) {
if (msg.type === 'log:reload') {
for (var k in stds){
if (typeof stds[k] == 'object' && !isNaN(stds[k].fd)){
if (stds[k].destroy) stds[k].destroy();
else if (stds[k].end) stds[k].end();
else if (stds[k].close) stds[k].close();
stds[k] = stds[k]._file;
}
}
Utility.startLogging(stds, function (err) {
if (err)
return console.error('Failed to reload logs:', err.stack);
console.log('Reloading log...');
});
}
});
var dayjs = null;
if (pm2_env.log_date_format)
dayjs = require('dayjs');
Utility.startLogging(stds, function (err) {
if (err) {
process.send({
type : 'process:exception',
data : {
message: err.message,
syscall: 'ProcessContainer.startLogging'
}
});
throw err;
return;
}
process.stderr.write = (function(write) {
return function(string, encoding, cb) {
var log_data = null;
// Disable logs if specified
if (pm2_env.disable_logs === true) {
return cb ? cb() : false;
}
if (pm2_env.log_type && pm2_env.log_type === 'json') {
log_data = JSON.stringify({
message : string.toString(),
timestamp : pm2_env.log_date_format && dayjs ?
dayjs().format(pm2_env.log_date_format) : new Date().toISOString(),
type : 'err',
process_id : pm2_env.pm_id,
app_name : pm2_env.name
}) + '\n';
}
else if (pm2_env.log_date_format && dayjs)
log_data = `${dayjs().format(pm2_env.log_date_format)}: ${string.toString()}`;
else
log_data = string.toString();
process.send({
type : 'log:err',
topic : 'log:err',
data : log_data
});
if (Utility.checkPathIsNull(pm2_env.pm_err_log_path) &&
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
return cb ? cb() : false;
stds.std && stds.std.write && stds.std.write(log_data, encoding);
stds.err && stds.err.write && stds.err.write(log_data, encoding, cb);
};
})(process.stderr.write);
process.stdout.write = (function(write) {
return function(string, encoding, cb) {
var log_data = null;
// Disable logs if specified
if (pm2_env.disable_logs === true) {
return cb ? cb() : false;
}
if (pm2_env.log_type && pm2_env.log_type === 'json') {
log_data = JSON.stringify({
message : string.toString(),
timestamp : pm2_env.log_date_format && dayjs ?
dayjs().format(pm2_env.log_date_format) : new Date().toISOString(),
type : 'out',
process_id : pm2_env.pm_id,
app_name : pm2_env.name
}) + '\n';
}
else if (pm2_env.log_date_format && dayjs)
log_data = `${dayjs().format(pm2_env.log_date_format)}: ${string.toString()}`;
else
log_data = string.toString();
process.send({
type : 'log:out',
data : log_data
});
if (Utility.checkPathIsNull(pm2_env.pm_out_log_path) &&
(!pm2_env.pm_log_path || Utility.checkPathIsNull(pm2_env.pm_log_path)))
return cb ? cb() : null;
stds.std && stds.std.write && stds.std.write(log_data, encoding);
stds.out && stds.out.write && stds.out.write(log_data, encoding, cb);
};
})(process.stdout.write);
function getUncaughtExceptionListener(listener) {
return function uncaughtListener(err) {
var error = err && err.stack ? err.stack : err;
if (listener === 'unhandledRejection') {
error = 'You have triggered an unhandledRejection, you may have forgotten to catch a Promise rejection:\n' + error;
}
logError(['std', 'err'], error);
// Notify master that an uncaughtException has been catched
try {
if (err) {
var errObj = {};
Object.getOwnPropertyNames(err).forEach(function(key) {
errObj[key] = err[key];
});
}
process.send({
type : 'log:err',
topic : 'log:err',
data : '\n' + error + '\n'
});
process.send({
type : 'process:exception',
data : errObj !== undefined ? errObj : {message: 'No error but ' + listener + ' was caught!'}
});
} catch(e) {
logError(['std', 'err'], 'Channel is already closed can\'t broadcast error:\n' + e.stack);
}
if (!process.listeners(listener).filter(function (listener) {
return listener !== uncaughtListener;
}).length) {
if (listener == 'uncaughtException') {
process.emit('disconnect');
process.exit(cst.CODE_UNCAUGHTEXCEPTION);
}
}
}
}
process.on('uncaughtException', getUncaughtExceptionListener('uncaughtException'));
process.on('unhandledRejection', getUncaughtExceptionListener('unhandledRejection'));
// Change dir to fix process.cwd
process.chdir(pm2_env.pm_cwd || process.env.PWD || p.dirname(script));
if (ProcessUtils.isESModule(script) === true)
import(Url.pathToFileURL(process.env.pm_exec_path));
else
require('module')._load(script, null, true);
function logError(types, error){
try {
types.forEach(function(type){
stds[type] && typeof stds[type].write == 'function' && stds[type].write(error + '\n');
});
} catch(e) { }
}
});
}

View File

@@ -0,0 +1,42 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var url = require('url');
// Inject custom modules
var ProcessUtils = require('./ProcessUtils')
ProcessUtils.injectModules()
if (typeof(process.env.source_map_support) != "undefined" &&
process.env.source_map_support !== "false") {
require('source-map-support').install();
}
// Rename the process
process.title = process.env.PROCESS_TITLE || 'node ' + process.env.pm_exec_path;
if (process.connected &&
process.send &&
process.versions &&
process.versions.node)
process.send({
'node_version': process.versions.node
});
// Require the real application
if (process.env.pm_exec_path) {
if (ProcessUtils.isESModule(process.env.pm_exec_path) === true) {
import(url.pathToFileURL(process.env.pm_exec_path));
}
else
require('module')._load(process.env.pm_exec_path, null, true);
}
else
throw new Error('Could not _load() the script');
// Change some values to make node think that the user's application
// was started directly such as `node app.js`
process.mainModule = process.mainModule || {};
process.mainModule.loaded = false;
require.main = process.mainModule;

55
api.hyungi.net/node_modules/pm2/lib/ProcessUtils.js generated vendored Normal file
View File

@@ -0,0 +1,55 @@
'use strict'
module.exports = {
injectModules: function() {
if (process.env.pmx !== 'false') {
const pmx = require('@pm2/io')
let conf = {}
const hasSpecificConfig = typeof process.env.io === 'string' || process.env.trace === 'true'
// pmx is already init, no need to do it twice
if (hasSpecificConfig === false) return
if (process.env.io) {
const io = JSON.parse(process.env.io)
conf = io.conf ? io.conf : conf
}
pmx.init(Object.assign({
tracing: process.env.trace === 'true' || false
}, conf))
}
},
isESModule(exec_path) {
var fs = require('fs')
var path = require('path')
var semver = require('semver')
var data
var findPackageJson = function(directory) {
var file = path.join(directory, 'package.json')
if (fs.existsSync(file) && fs.statSync(file).isFile()) {
return file;
}
var parent = path.resolve(directory, '..')
if (parent === directory) {
return null;
}
return findPackageJson(parent)
}
if (semver.satisfies(process.version, '< 13.3.0'))
return false
if (path.extname(exec_path) === '.mjs')
return true
try {
data = JSON.parse(fs.readFileSync(findPackageJson(path.dirname(exec_path))))
if (data.type === 'module')
return true
else
return false
} catch(e) {
}
}
}

117
api.hyungi.net/node_modules/pm2/lib/TreeKill.js generated vendored Normal file
View File

@@ -0,0 +1,117 @@
'use strict';
// From https://raw.githubusercontent.com/pkrumins/node-tree-kill/master/index.js
var childProcess = require('child_process');
var spawn = childProcess.spawn;
var exec = childProcess.exec;
module.exports = function (pid, signal, callback) {
var tree = {};
var pidsToProcess = {};
tree[pid] = [];
pidsToProcess[pid] = 1;
switch (process.platform) {
case 'win32':
exec('taskkill /pid ' + pid + ' /T /F', { windowsHide: true }, callback);
break;
case 'darwin':
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
return spawn('pgrep', ['-P', parentPid]);
}, function () {
killAll(tree, signal, callback);
});
break;
// case 'sunos':
// buildProcessTreeSunOS(pid, tree, pidsToProcess, function () {
// killAll(tree, signal, callback);
// });
// break;
default: // Linux
buildProcessTree(pid, tree, pidsToProcess, function (parentPid) {
return spawn('ps', ['-o', 'pid', '--no-headers', '--ppid', parentPid]);
}, function () {
killAll(tree, signal, callback);
});
break;
}
};
function killAll (tree, signal, callback) {
var killed = {};
try {
Object.keys(tree).forEach(function (pid) {
tree[pid].forEach(function (pidpid) {
if (!killed[pidpid]) {
killPid(pidpid, signal);
killed[pidpid] = 1;
}
});
if (!killed[pid]) {
killPid(pid, signal);
killed[pid] = 1;
}
});
} catch (err) {
if (callback) {
return callback(err);
} else {
console.error(err);
}
}
if (callback) {
return callback();
}
}
function killPid(pid, signal) {
try {
process.kill(parseInt(pid, 10), signal);
}
catch (err) {
if (err.code !== 'ESRCH')
console.error(err);
}
}
function buildProcessTree (parentPid, tree, pidsToProcess, spawnChildProcessesList, cb) {
var ps = spawnChildProcessesList(parentPid);
var allData = '';
ps.on('error', function(err) {
console.error(err);
});
if (ps.stdout) {
ps.stdout.on('data', function (data) {
data = data.toString('ascii');
allData += data;
});
}
var onClose = function (code) {
delete pidsToProcess[parentPid];
if (code !== 0) {
// no more parent processes
if (Object.keys(pidsToProcess).length == 0) {
cb();
}
return;
}
var pids = allData.match(/\d+/g) || [];
if (pids.length === 0)
return cb();
pids.forEach(function (pid) {
pid = parseInt(pid, 10);
tree[parentPid].push(pid);
tree[pid] = [];
pidsToProcess[pid] = 1;
buildProcessTree(pid, tree, pidsToProcess, spawnChildProcessesList, cb);
});
};
ps.on('close', onClose);
}

278
api.hyungi.net/node_modules/pm2/lib/Utility.js generated vendored Normal file
View File

@@ -0,0 +1,278 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
/**
* Common Utilities ONLY USED IN ->DAEMON<-
*/
var fclone = require('fclone');
var fs = require('fs');
var cst = require('../constants.js');
var waterfall = require('async/waterfall');
var util = require('util');
var url = require('url');
var dayjs = require('dayjs');
var findPackageJson = require('./tools/find-package-json')
var Utility = module.exports = {
findPackageVersion : function(fullpath) {
var version
try {
version = findPackageJson(fullpath).next().value.version
} catch(e) {
version = 'N/A'
}
return version
},
getDate : function() {
return Date.now();
},
extendExtraConfig : function(proc, opts) {
if (opts.env && opts.env.current_conf) {
if (opts.env.current_conf.env &&
typeof(opts.env.current_conf.env) === 'object' &&
Object.keys(opts.env.current_conf.env).length === 0)
delete opts.env.current_conf.env
Utility.extendMix(proc.pm2_env, opts.env.current_conf);
delete opts.env.current_conf;
}
},
formatCLU : function(process) {
if (!process.pm2_env) {
return process;
}
var obj = Utility.clone(process.pm2_env);
delete obj.env;
return obj;
},
extend : function(destination, source){
if (!source || typeof source != 'object') return destination;
Object.keys(source).forEach(function(new_key) {
if (source[new_key] != '[object Object]')
destination[new_key] = source[new_key];
});
return destination;
},
// Same as extend but drop value with 'null'
extendMix : function(destination, source){
if (!source || typeof source != 'object') return destination;
Object.keys(source).forEach(function(new_key) {
if (source[new_key] == 'null')
delete destination[new_key];
else
destination[new_key] = source[new_key]
});
return destination;
},
whichFileExists : function(file_arr) {
var f = null;
file_arr.some(function(file) {
try {
fs.statSync(file);
} catch(e) {
return false;
}
f = file;
return true;
});
return f;
},
clone : function(obj) {
if (obj === null || obj === undefined) return {};
return fclone(obj);
},
overrideConsole : function(bus) {
if (cst.PM2_LOG_DATE_FORMAT && typeof cst.PM2_LOG_DATE_FORMAT == 'string') {
// Generate timestamp prefix
function timestamp(){
return `${dayjs(Date.now()).format(cst.PM2_LOG_DATE_FORMAT)}:`;
}
var hacks = ['info', 'log', 'error', 'warn'], consoled = {};
// store console functions.
hacks.forEach(function(method){
consoled[method] = console[method];
});
hacks.forEach(function(k){
console[k] = function(){
if (bus) {
bus.emit('log:PM2', {
process : {
pm_id : 'PM2',
name : 'PM2',
rev : null
},
at : Utility.getDate(),
data : util.format.apply(this, arguments) + '\n'
});
}
// do not destroy variable insertion
arguments[0] && (arguments[0] = timestamp() + ' PM2 ' + k + ': ' + arguments[0]);
consoled[k].apply(console, arguments);
};
});
}
},
startLogging : function(stds, callback) {
/**
* Start log outgoing messages
* @method startLogging
* @param {} callback
* @return
*/
// Make sure directories of `logs` and `pids` exist.
// try {
// ['logs', 'pids'].forEach(function(n){
// console.log(n);
// (function(_path){
// !fs.existsSync(_path) && fs.mkdirSync(_path, '0755');
// })(path.resolve(cst.PM2_ROOT_PATH, n));
// });
// } catch(err) {
// return callback(new Error('can not create directories (logs/pids):' + err.message));
// }
// waterfall.
var flows = [];
// types of stdio, should be sorted as `std(entire log)`, `out`, `err`.
var types = Object.keys(stds).sort(function(x, y){
return -x.charCodeAt(0) + y.charCodeAt(0);
});
// Create write streams.
(function createWS(io){
if(io.length != 1){
return false;
}
io = io[0];
// If `std` is a Stream type, try next `std`.
// compatible with `pm2 reloadLogs`
if(typeof stds[io] == 'object' && !isNaN(stds[io].fd)){
return createWS(types.splice(0, 1));
}
flows.push(function(next){
var file = stds[io];
// if file contains ERR or /dev/null, dont try to create stream since he dont want logs
if (!file || file.indexOf('NULL') > -1 || file.indexOf('/dev/null') > -1)
return next();
stds[io] = fs.createWriteStream(file, {flags: 'a'})
.once('error', next)
.on('open', function(){
stds[io].removeListener('error', next);
stds[io].on('error', function(err) {
console.error(err);
});
next();
});
stds[io]._file = file;
});
return createWS(types.splice(0, 1));
})(types.splice(0, 1));
waterfall(flows, callback);
},
/**
* Function parse the module name and returns it as canonic:
* - Makes the name based on installation filename.
* - Removes the Github author, module version and git branch from original name.
*
* @param {string} module_name
* @returns {string} Canonic module name (without trimed parts).
* @example Always returns 'pm2-slack' for inputs 'ma-zal/pm2-slack', 'ma-zal/pm2-slack#own-branch',
* 'pm2-slack-1.0.0.tgz' or 'pm2-slack@1.0.0'.
*/
getCanonicModuleName: function(module_name) {
if (typeof module_name !== 'string') return null;
var canonic_module_name = module_name;
// Returns the module name from a .tgz package name (or the original name if it is not a valid pkg).
// Input: The package name (e.g. "foo.tgz", "foo-1.0.0.tgz", "folder/foo.tgz")
// Output: The module name
if (canonic_module_name.match(/\.tgz($|\?)/)) {
if (canonic_module_name.match(/^(.+\/)?([^\/]+)\.tgz($|\?)/)) {
canonic_module_name = canonic_module_name.match(/^(.+\/)?([^\/]+)\.tgz($|\?)/)[2];
if (canonic_module_name.match(/^(.+)-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+\.[0-9]+)?$/)) {
canonic_module_name = canonic_module_name.match(/^(.+)-[0-9]+\.[0-9]+\.[0-9]+(-[a-zA-Z0-9_]+\.[0-9]+)?$/)[1];
}
}
}
//pm2 install git+https://github.com/user/module
if(canonic_module_name.indexOf('git+') !== -1) {
canonic_module_name = canonic_module_name.split('/').pop();
}
//pm2 install https://github.com/user/module
if(canonic_module_name.indexOf('http') !== -1) {
var uri = url.parse(canonic_module_name);
canonic_module_name = uri.pathname.split('/').pop();
}
//pm2 install file:///home/user/module
else if(canonic_module_name.indexOf('file://') === 0) {
canonic_module_name = canonic_module_name.replace(/\/$/, '').split('/').pop();
}
//pm2 install username/module
else if(canonic_module_name.indexOf('/') !== -1) {
if (canonic_module_name.charAt(0) !== "@"){
canonic_module_name = canonic_module_name.split('/')[1];
}
}
//pm2 install @somescope/module@2.1.0-beta
if(canonic_module_name.lastIndexOf('@') > 0) {
canonic_module_name = canonic_module_name.substr(0,canonic_module_name.lastIndexOf("@"));
}
//pm2 install module#some-branch
if(canonic_module_name.indexOf('#') !== -1) {
canonic_module_name = canonic_module_name.split('#')[0];
}
if (canonic_module_name.indexOf('.git') !== -1) {
canonic_module_name = canonic_module_name.replace('.git', '');
}
return canonic_module_name;
},
checkPathIsNull: function(path) {
return path === 'NULL' || path === '/dev/null' || path === '\\\\.\\NUL';
},
generateUUID: function () {
var s = [];
var hexDigits = "0123456789abcdef";
for (var i = 0; i < 36; i++) {
s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
}
s[14] = "4";
s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
s[8] = s[13] = s[18] = s[23] = "-";
return s.join("");
}
};

46
api.hyungi.net/node_modules/pm2/lib/VersionCheck.js generated vendored Normal file
View File

@@ -0,0 +1,46 @@
var vCheck = require('@pm2/pm2-version-check')
var semver = require('semver')
var fs = require('fs')
var os = require('os')
function hasDockerEnv() {
try {
fs.statSync('/.dockerenv');
return true;
} catch (_) {
return false;
}
}
function hasDockerCGroup() {
try {
return fs.readFileSync('/proc/self/cgroup', 'utf8').includes('docker');
} catch (_) {
return false;
}
}
module.exports = function (opts) {
var params = {
state: opts.state,
version: opts.version
}
try {
params.os = os.type()
params.uptime = Math.floor(process.uptime())
params.nodev = process.versions.node
params.docker = hasDockerEnv() || hasDockerCGroup()
} catch(e) {
}
vCheck.runCheck(params, (err, pkg) => {
if (err) return false
if (!pkg.current_version) return false
if (opts.version && semver.lt(opts.version, pkg.current_version)) {
console.log('[PM2] This PM2 is not UP TO DATE')
console.log('[PM2] Upgrade to version %s', pkg.current_version)
}
})
}

117
api.hyungi.net/node_modules/pm2/lib/Watcher.js generated vendored Normal file
View File

@@ -0,0 +1,117 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var chokidar = require('chokidar');
var util = require('util');
var log = require('debug')('pm2:watch');
module.exports = function ClusterMode(God) {
/**
* Watch folder for changes and restart
* @method watch
* @param {Object} pm2_env pm2 app environnement
* @return MemberExpression
*/
God.watch = {};
God.watch._watchers = {};
God.watch.enable = function(pm2_env) {
if (God.watch._watchers[pm2_env.pm_id]) {
God.watch._watchers[pm2_env.pm_id].close();
God.watch._watchers[pm2_env.pm_id] = null;
delete God.watch._watchers[pm2_env.pm_id];
}
log('Initial watch ', pm2_env.watch)
var watch = pm2_env.watch
if(typeof watch == 'boolean' || Array.isArray(watch) && watch.length === 0)
watch = pm2_env.pm_cwd;
log('Watching %s', watch);
var watch_options = {
ignored : pm2_env.ignore_watch || /[\/\\]\.|node_modules/,
persistent : true,
ignoreInitial : true,
cwd: pm2_env.pm_cwd
};
if (pm2_env.watch_options) {
watch_options = Object.assign(watch_options, pm2_env.watch_options);
}
log('Watch opts', watch_options);
var watcher = chokidar.watch(watch, watch_options);
console.log('[Watch] Start watching', pm2_env.name);
watcher.on('all', function(event, path) {
var self = this;
if (self.restarting === true) {
log('Already restarting, skipping');
return false;
}
self.restarting = true;
console.log('Change detected on path %s for app %s - restarting', path, pm2_env.name);
setTimeout(function() {
God.restartProcessName(pm2_env.name, function(err, list) {
self.restarting = false;
if (err) {
log('Error while restarting', err);
return false;
}
return log('Process restarted');
});
}, (pm2_env.watch_delay || 0));
return false;
});
watcher.on('error', function(e) {
console.error(e.stack || e);
});
God.watch._watchers[pm2_env.pm_id] = watcher;
//return God.watch._watchers[pm2_env.name];
},
/**
* Description
* @method close
* @param {} id
* @return
*/
God.watch.disableAll = function() {
var watchers = God.watch._watchers;
console.log('[Watch] PM2 is being killed. Watch is disabled to avoid conflicts');
for (var i in watchers) {
watchers[i].close && watchers[i].close();
watchers.splice(i, 1);
}
},
God.watch.disable = function(pm2_env) {
var watcher = God.watch._watchers[pm2_env.pm_id]
if (watcher) {
console.log('[Watch] Stop watching', pm2_env.name);
watcher.close();
delete God.watch._watchers[pm2_env.pm_id];
return true;
} else {
return false;
}
}
};

213
api.hyungi.net/node_modules/pm2/lib/Worker.js generated vendored Normal file
View File

@@ -0,0 +1,213 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
const vizion = require('vizion');
const eachLimit = require('async/eachLimit');
const debug = require('debug')('pm2:worker');
const domain = require('domain');
const Cron = require('croner');
const pkg = require('../package.json');
var cst = require('../constants.js');
var vCheck = require('./VersionCheck.js')
module.exports = function(God) {
var timer = null;
God.CronJobs = new Map();
God.Worker = {};
God.Worker.is_running = false;
God.getCronID = function(pm_id) {
return `cron-${pm_id}`
}
God.registerCron = function(pm2_env) {
if (!pm2_env ||
pm2_env.pm_id === undefined ||
!pm2_env.cron_restart ||
pm2_env.cron_restart == '0' ||
God.CronJobs.has(God.getCronID(pm2_env.pm_id)))
return;
var pm_id = pm2_env.pm_id
console.log('[PM2][WORKER] Registering a cron job on:', pm_id);
var job = Cron(pm2_env.cron_restart, function() {
God.restartProcessId({id: pm_id}, function(err, data) {
if (err)
console.error(err.stack || err);
return;
});
});
God.CronJobs.set(God.getCronID(pm_id), job);
}
/**
* Deletes the cron job on deletion of process
*/
God.deleteCron = function(id) {
if (typeof(id) !== 'undefined' && God.CronJobs.has(God.getCronID(id)) === false)
return;
console.log('[PM2] Deregistering a cron job on:', id);
var job = God.CronJobs.get(God.getCronID(id));
if (job)
job.stop();
God.CronJobs.delete(God.getCronID(id));
};
var _getProcessById = function(pm_id) {
var proc = God.clusters_db[pm_id];
return proc ? proc : null;
};
var maxMemoryRestart = function(proc_key, cb) {
var proc = _getProcessById(proc_key.pm2_env.pm_id);
if (!(proc &&
proc.pm2_env &&
proc_key.monit))
return cb();
if (proc_key.monit.memory !== undefined &&
proc.pm2_env.max_memory_restart !== undefined &&
proc.pm2_env.max_memory_restart < proc_key.monit.memory &&
proc.pm2_env.axm_options &&
proc.pm2_env.axm_options.pid === undefined) {
console.log('[PM2][WORKER] Process %s restarted because it exceeds --max-memory-restart value (current_memory=%s max_memory_limit=%s [octets])', proc.pm2_env.pm_id, proc_key.monit.memory, proc.pm2_env.max_memory_restart);
God.reloadProcessId({
id : proc.pm2_env.pm_id
}, function(err, data) {
if (err)
console.error(err.stack || err);
return cb();
});
}
else {
return cb();
}
};
// Deprecated
var versioningRefresh = function(proc_key, cb) {
var proc = _getProcessById(proc_key.pm2_env.pm_id);
if (!(proc &&
proc.pm2_env &&
(proc.pm2_env.vizion !== false && proc.pm2_env.vizion != "false") &&
proc.pm2_env.versioning &&
proc.pm2_env.versioning.repo_path)) {
return cb();
}
if (proc.pm2_env.vizion_running === true)
{
debug('Vizion is already running for proc id: %d, skipping this round', proc.pm2_env.pm_id);
return cb();
}
proc.pm2_env.vizion_running = true;
var repo_path = proc.pm2_env.versioning.repo_path;
vizion.analyze({
folder: proc.pm2_env.versioning.repo_path
},
function(err, meta) {
if (err != null)
return cb();
proc = _getProcessById(proc_key.pm2_env.pm_id);
if (!(proc &&
proc.pm2_env &&
proc.pm2_env.versioning &&
proc.pm2_env.versioning.repo_path)) {
console.error('Proc not defined anymore or versioning unknown');
return cb();
}
proc.pm2_env.vizion_running = false;
meta.repo_path = repo_path;
proc.pm2_env.versioning = meta;
debug('[PM2][WORKER] %s parsed for versioning', proc.pm2_env.name);
return cb();
});
};
var tasks = function() {
if (God.Worker.is_running === true) {
debug('[PM2][WORKER] Worker is already running, skipping this round');
return false;
}
God.Worker.is_running = true;
God.getMonitorData(null, function(err, data) {
if (err || !data || typeof(data) !== 'object') {
God.Worker.is_running = false;
return console.error(err);
}
eachLimit(data, 1, function(proc, next) {
if (!proc || !proc.pm2_env || proc.pm2_env.pm_id === undefined)
return next();
debug('[PM2][WORKER] Processing proc id:', proc.pm2_env.pm_id);
// Reset restart delay if application has an uptime of more > 30secs
if (proc.pm2_env.exp_backoff_restart_delay !== undefined &&
proc.pm2_env.prev_restart_delay && proc.pm2_env.prev_restart_delay > 0) {
var app_uptime = Date.now() - proc.pm2_env.pm_uptime
if (app_uptime > cst.EXP_BACKOFF_RESET_TIMER) {
var ref_proc = _getProcessById(proc.pm2_env.pm_id);
ref_proc.pm2_env.prev_restart_delay = 0
console.log(`[PM2][WORKER] Reset the restart delay, as app ${proc.name} has been up for more than ${cst.EXP_BACKOFF_RESET_TIMER}ms`)
}
}
// Check if application has reached memory threshold
maxMemoryRestart(proc, function() {
return next();
});
}, function(err) {
God.Worker.is_running = false;
debug('[PM2][WORKER] My job here is done, next job in %d seconds', parseInt(cst.WORKER_INTERVAL / 1000));
});
});
};
var wrappedTasks = function() {
var d = domain.create();
d.once('error', function(err) {
console.error('[PM2][WORKER] Error caught by domain:\n' + (err.stack || err));
God.Worker.is_running = false;
});
d.run(function() {
tasks();
});
};
God.Worker.start = function() {
timer = setInterval(wrappedTasks, cst.WORKER_INTERVAL);
setInterval(() => {
vCheck({
state: 'check',
version: pkg.version
})
}, 1000 * 60 * 60 * 24)
};
God.Worker.stop = function() {
if (timer !== null)
clearInterval(timer);
};
};

1033
api.hyungi.net/node_modules/pm2/lib/binaries/CLI.js generated vendored Normal file

File diff suppressed because it is too large Load Diff

183
api.hyungi.net/node_modules/pm2/lib/binaries/DevCLI.js generated vendored Normal file
View File

@@ -0,0 +1,183 @@
'use strict';
process.env.PM2_NO_INTERACTION = 'true';
// Do not print banner
process.env.PM2_DISCRETE_MODE = true;
var commander = require('commander');
var PM2 = require('../..');
var Log = require('../API/Log');
var cst = require('../../constants.js');
var pkg = require('../../package.json');
var chalk = require('chalk');
var path = require('path');
var fmt = require('../tools/fmt.js');
var exec = require('child_process').exec;
var os = require('os');
commander.version(pkg.version)
.description('pm2-dev monitor for any file changes and automatically restart it')
.option('--raw', 'raw log output')
.option('--timestamp', 'print timestamp')
.option('--node-args <node_args>', 'space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"')
.option('--ignore [files]', 'files to ignore while watching')
.option('--post-exec [cmd]', 'execute extra command after change detected')
.option('--silent-exec', 'do not output result of post command', false)
.option('--test-mode', 'debug mode for test suit')
.option('--interpreter <interpreter>', 'the interpreter pm2 should use for executing app (bash, python...)')
.option('--env [name]', 'select env_[name] env variables in process config file')
.option('--auto-exit', 'exit if all processes are errored/stopped or 0 apps launched')
.usage('pm2-dev app.js');
var pm2 = new PM2.custom({
pm2_home : path.join(os.homedir ? os.homedir() : (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE), '.pm2-dev')
});
pm2.connect(function() {
commander.parse(process.argv);
});
function postExecCmd(command, cb) {
var exec_cmd = exec(command);
if (commander.silentExec !== true) {
exec_cmd.stdout.on('data', function(data) {
process.stdout.write(data);
});
exec_cmd.stderr.on('data', function(data) {
process.stderr.write(data);
});
}
exec_cmd.on('close', function done() {
if (cb) cb(null);
});
exec_cmd.on('error', function (err) {
console.error(err.stack || err);
});
};
function run(cmd, opts) {
var timestamp = opts.timestamp;
opts.watch = true;
opts.autostart = true;
opts.autorestart = true;
opts.restart_delay = 1000
if (opts.autoExit)
autoExit();
if (opts.ignore) {
opts.ignore_watch = opts.ignore.split(',')
opts.ignore_watch.push('node_modules');
}
if (timestamp === true)
timestamp = 'YYYY-MM-DD-HH:mm:ss';
pm2.start(cmd, opts, function(err, procs) {
if (err) {
console.error(err);
pm2.destroy(function() {
process.exit(0);
});
return false;
}
if (opts.testMode) {
return pm2.disconnect(function() {
});
}
fmt.sep();
fmt.title('PM2 development mode');
fmt.field('Apps started', procs.map(function(p) { return p.pm2_env.name } ));
fmt.field('Processes started', chalk.bold(procs.length));
fmt.field('Watch and Restart', chalk.green('Enabled'));
fmt.field('Ignored folder', opts.ignore_watch || 'node_modules');
if (opts.postExec)
fmt.field('Post restart cmd', opts.postExec);
fmt.sep();
setTimeout(function() {
pm2.Client.launchBus(function(err, bus) {
bus.on('process:event', function(packet) {
if (packet.event == 'online') {
if (opts.postExec)
postExecCmd(opts.postExec);
}
});
});
}, 1000);
Log.devStream(pm2.Client, 'all', opts.raw, timestamp, false);
process.on('SIGINT', function() {
console.log('>>>>> [PM2 DEV] Stopping current development session');
pm2.delete('all', function() {
pm2.destroy(function() {
process.exit(0);
});
});
});
});
}
commander.command('*')
.action(function(cmd, opts){
run(cmd, commander);
});
commander.command('start <file|json_file>')
.description('start target config file/script in development mode')
.action(function(cmd, opts) {
run(cmd, commander);
});
function exitPM2() {
if (pm2 && pm2.connected == true) {
console.log(chalk.green.bold('>>> Exiting PM2'));
pm2.kill(function() {
process.exit(0);
});
}
else
process.exit(0);
}
function autoExit(final) {
setTimeout(function() {
pm2.list(function(err, apps) {
if (err) console.error(err.stack || err);
var online_count = 0;
apps.forEach(function(app) {
if (app.pm2_env.status == cst.ONLINE_STATUS ||
app.pm2_env.status == cst.LAUNCHING_STATUS)
online_count++;
});
if (online_count == 0) {
console.log('0 application online, exiting');
if (final == true)
process.exit(1);
else
autoExit(true);
return false;
}
autoExit(false);
});
}, 3000);
}
if (process.argv.length == 2) {
commander.outputHelp();
exitPM2();
}

101
api.hyungi.net/node_modules/pm2/lib/binaries/Runtime.js generated vendored Normal file
View File

@@ -0,0 +1,101 @@
'use strict';
var commander = require('commander');
var PM2 = require('../..');
var Log = require('../../lib/API/Log');
var cst = require('../../constants.js');
var pkg = require('../../package.json');
var path = require('path');
var pm2;
// Do not print banner
process.env.PM2_DISCRETE_MODE = true;
commander.version(pkg.version)
.description('pm2-runtime is an automatic pmx injection that runs in simulated no-daemon environment')
.option('--auto-manage', 'keep application online after command exit')
.option('--fast-boot', 'boot app faster by keeping pm2 runtime online in background (effective at second exit/start)')
.option('--web [port]', 'launch process web api on [port] default to 9615')
.option('--secret [key]', 'PM2 plus secret key')
.option('--public [key]', 'PM2 plus public key')
.option('--machine-name [name]', 'PM2 plus machine name')
.option('--env [name]', 'select env_[name] env variables in process config file')
.option('--watch', 'Watch and Restart')
.option('-i --instances <number>', 'launch [number] instances with load-balancer')
.usage('pm2-runtime app.js');
commander.command('*')
.action(function(cmd){
pm2 = new PM2.custom({
pm2_home : path.join(process.env.HOME, '.pm3'),
secret_key : cst.SECRET_KEY || commander.secret,
public_key : cst.PUBLIC_KEY || commander.public,
machine_name : cst.MACHINE_NAME || commander.machineName
});
pm2.connect(function() {
if (commander.web) {
var port = commander.web === true ? cst.WEB_PORT : commander.web;
pm2.web(port);
}
pm2.start(cmd, commander, function(err, obj) {
if (process.env.PM2_RUNTIME_DEBUG) {
return pm2.disconnect(function() {});
}
if (err) {
console.error(err);
return process.exit(1);
}
var pm_id = obj[0].pm2_env.pm_id;
if (commander.instances == undefined) {
return pm2.attach(pm_id, function() {
exitPM2();
});
}
if (commander.json === true)
Log.jsonStream(pm2.Client, pm_id);
else if (commander.format === true)
Log.formatStream(pm2.Client, pm_id, false, 'YYYY-MM-DD-HH:mm:ssZZ');
else
Log.stream(pm2.Client, 'all', true);
});
});
});
if (process.argv.length == 2) {
commander.outputHelp();
process.exit(1);
}
process.on('SIGINT', function() {
exitPM2();
});
process.on('SIGTERM', function() {
exitPM2();
});
commander.parse(process.argv);
function exitPM2() {
console.log('Exited at %s', new Date());
if (commander.autoManage)
return process.exit(0);
if (commander.fastBoot) {
return pm2.delete('all', function() {
process.exit(0);
});
}
pm2.kill(function() {
process.exit(0);
});
}

View File

@@ -0,0 +1,192 @@
'use strict';
/**
* Specialized PM2 CLI for Containers
*/
var commander = require('commander');
var PM2 = require('../..');
var Log = require('../../lib/API/Log');
var cst = require('../../constants.js');
var pkg = require('../../package.json');
var path = require('path');
var DEFAULT_FAIL_COUNT = 3;
process.env.PM2_DISCRETE_MODE = true;
commander.version(pkg.version)
.description('pm2-runtime is a drop-in replacement Node.js binary for containers')
.option('-i --instances <number>', 'launch [number] of processes automatically load-balanced. Increase overall performances and performance stability.')
.option('--secret [key]', '[MONITORING] PM2 plus secret key')
.option('--no-autostart', 'add an app without automatic start')
.option('--no-autorestart', 'start an app without automatic restart')
.option('--stop-exit-codes <exit_codes...>', 'specify a list of exit codes that should skip automatic restart')
.option('--node-args <node_args>', 'space delimited arguments to pass to node in cluster mode - e.g. --node-args="--debug=7001 --trace-deprecation"')
.option('-n --name <name>', 'set a <name> for script')
.option('--max-memory-restart <memory>', 'specify max memory amount used to autorestart (in octet or use syntax like 100M)')
.option('-c --cron <cron_pattern>', 'restart a running process based on a cron pattern')
.option('--interpreter <interpreter>', 'the interpreter pm2 should use for executing app (bash, python...)')
.option('--public [key]', '[MONITORING] PM2 plus public key')
.option('--machine-name [name]', '[MONITORING] PM2 plus machine name')
.option('--trace', 'enable transaction tracing with km')
.option('--v8', 'enable v8 data collecting')
.option('--format', 'output logs formated like key=val')
.option('--raw', 'raw output (default mode)')
.option('--formatted', 'formatted log output |id|app|log')
.option('--json', 'output logs in json format')
.option('--delay <seconds>', 'delay start of configuration file by <seconds>', 0)
.option('--web [port]', 'launch process web api on [port] (default to 9615)')
.option('--only <application-name>', 'only act on one application of configuration')
.option('--no-auto-exit', 'do not exit if all processes are errored/stopped or 0 apps launched')
.option('--env [name]', 'inject env_[name] env variables in process config file')
.option('--watch', 'watch and restart application on file change')
.option('--error <path>', 'error log file destination (default disabled)', '/dev/null')
.option('--output <path>', 'output log file destination (default disabled)', '/dev/null')
.option('--deep-monitoring', 'enable all monitoring tools (equivalent to --v8 --event-loop-inspector --trace)')
.allowUnknownOption()
.usage('app.js');
commander.command('*')
.action(function(cmd){
Runtime.instanciate(cmd);
});
commander.command('start <app.js|json_file>')
.description('start an application or json ecosystem file')
.action(function(cmd) {
Runtime.instanciate(cmd);
});
if (process.argv.length == 2) {
commander.outputHelp();
process.exit(1);
}
var Runtime = {
pm2 : null,
instanciate : function(cmd) {
this.pm2 = new PM2.custom({
pm2_home : process.env.PM2_HOME || path.join(process.env.HOME, '.pm2'),
secret_key : cst.SECRET_KEY || commander.secret,
public_key : cst.PUBLIC_KEY || commander.public,
machine_name : cst.MACHINE_NAME || commander.machineName,
daemon_mode : process.env.PM2_RUNTIME_DEBUG || false
});
this.pm2.connect(function(err, pm2_meta) {
process.on('SIGINT', function() {
Runtime.exit();
});
process.on('SIGTERM', function() {
Runtime.exit();
});
Runtime.startLogStreaming();
Runtime.startApp(cmd, function(err) {
if (err) {
console.error(err.message || err);
return Runtime.exit();
}
});
});
},
/**
* Log Streaming Management
*/
startLogStreaming : function() {
if (commander.json === true)
Log.jsonStream(this.pm2.Client, 'all');
else if (commander.format === true)
Log.formatStream(this.pm2.Client, 'all', false, 'YYYY-MM-DD-HH:mm:ssZZ');
else
Log.stream(this.pm2.Client, 'all', !commander.formatted, commander.timestamp, true);
},
/**
* Application Startup
*/
startApp : function(cmd, cb) {
function exec() {
this.pm2.start(cmd, commander, function(err, obj) {
if (err)
return cb(err);
if (obj && obj.length == 0)
return cb(new Error(`0 application started (no apps to run on ${cmd})`))
if (commander.web) {
var port = commander.web === true ? cst.WEB_PORT : commander.web;
Runtime.pm2.web(port);
}
if (commander.autoExit) {
setTimeout(function() {
Runtime.autoExitWorker();
}, 4000);
}
// For Testing purpose (allow to auto exit CLI)
if (process.env.PM2_RUNTIME_DEBUG)
Runtime.pm2.disconnect(function() {});
return cb(null, obj);
});
}
// via --delay <seconds> option
setTimeout(exec.bind(this), commander.delay * 1000);
},
/**
* Exit runtime mgmt
*/
exit : function(code) {
if (!this.pm2) return process.exit(1);
this.pm2.kill(function() {
process.exit(code || 0);
});
},
/**
* Exit current PM2 instance if 0 app is online
* function activated via --auto-exit
*/
autoExitWorker : function(fail_count) {
var interval = 2000;
if (typeof(fail_count) =='undefined')
fail_count = DEFAULT_FAIL_COUNT;
var timer = setTimeout(function () {
Runtime.pm2.list(function (err, apps) {
if (err) {
console.error('Could not run pm2 list');
return Runtime.autoExitWorker();
}
var appOnline = 0;
apps.forEach(function (app) {
if (!app.pm2_env.pmx_module &&
(app.pm2_env.status === cst.ONLINE_STATUS ||
app.pm2_env.status === cst.LAUNCHING_STATUS)) {
appOnline++;
}
});
if (appOnline === 0) {
console.log('0 application online, retry =', fail_count);
if (fail_count <= 0)
return Runtime.exit(2);
return Runtime.autoExitWorker(--fail_count);
}
Runtime.autoExitWorker();
});
}, interval);
timer.unref();
}
}
commander.parse(process.argv);

229
api.hyungi.net/node_modules/pm2/lib/completion.js generated vendored Normal file
View File

@@ -0,0 +1,229 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var fs = require('fs'),
pth = require('path');
// hacked from node-tabtab 0.0.4 https://github.com/mklabs/node-tabtab.git
// Itself based on npm completion by @isaac
exports.complete = function complete(name, completer, cb) {
// cb not there, assume callback is completer and
// the completer is the executable itself
if(!cb) {
cb = completer;
completer = name;
}
var env = parseEnv();
// if not a complete command, return here.
if(!env.complete) return cb();
// if install cmd, add complete script to either ~/.bashrc or ~/.zshrc
if(env.install) return install(name, completer, function(err, state) {
console.log(state || err.message);
if(err) return cb(err);
cb(null, null, state);
});
// if install cmd, add complete script to either ~/.bashrc or ~/.zshrc
if(env.uninstall) return uninstall(name, completer, function(err, state) {
console.log(state || err.message);
if(err) return cb(err);
cb(null, null, state);
});
// if the COMP_* are not in the env, then dump the install script.
if(!env.words || !env.point || !env.line) return script(name, completer, function(err, content) {
if(err) return cb(err);
process.stdout.write(content, function (n) { cb(null, null, content); });
process.stdout.on("error", function (er) {
// Darwin is a real dick sometimes.
//
// This is necessary because the "source" or "." program in
// bash on OS X closes its file argument before reading
// from it, meaning that you get exactly 1 write, which will
// work most of the time, and will always raise an EPIPE.
//
// Really, one should not be tossing away EPIPE errors, or any
// errors, so casually. But, without this, `. <(npm completion)`
// can never ever work on OS X.
// -- isaacs
// https://github.com/isaacs/npm/blob/master/lib/completion.js#L162
if (er.errno === "EPIPE") er = null
cb(er, null, content);
});
cb(null, null, content);
});
var partial = env.line.substr(0, env.point),
last = env.line.split(' ').slice(-1).join(''),
lastPartial = partial.split(' ').slice(-1).join(''),
prev = env.line.split(' ').slice(0, -1).slice(-1)[0];
cb(null, {
line: env.line,
words: env.words,
point: env.point,
partial: partial,
last: last,
prev: prev,
lastPartial: lastPartial
});
};
// simple helper function to know if the script is run
// in the context of a completion command. Also mapping the
// special `<pkgname> completion` cmd.
exports.isComplete = function isComplete() {
var env = parseEnv();
return env.complete || (env.words && env.point && env.line);
};
exports.parseOut = function parseOut(str) {
var shorts = str.match(/\s-\w+/g);
var longs = str.match(/\s--\w+/g);
return {
shorts: shorts.map(trim).map(cleanPrefix),
longs: longs.map(trim).map(cleanPrefix)
};
};
// specific to cake case
exports.parseTasks = function(str, prefix, reg) {
var tasks = str.match(reg || new RegExp('^' + prefix + '\\s[^#]+', 'gm')) || [];
return tasks.map(trim).map(function(s) {
return s.replace(prefix + ' ', '');
});
};
exports.log = function log(arr, o, prefix) {
prefix = prefix || '';
arr = Array.isArray(arr) ? arr : [arr];
arr.filter(abbrev(o)).forEach(function(v) {
console.log(prefix + v);
});
}
function trim (s) {
return s.trim();
}
function cleanPrefix(s) {
return s.replace(/-/g, '');
}
function abbrev(o) { return function(it) {
return new RegExp('^' + o.last.replace(/^--?/g, '')).test(it);
}}
// output the completion.sh script to the console for install instructions.
// This is actually a 'template' where the package name is used to setup
// the completion on the right command, and properly name the bash/zsh functions.
function script(name, completer, cb) {
var p = pth.join(__dirname, 'completion.sh');
fs.readFile(p, 'utf8', function (er, d) {
if (er) return cb(er);
cb(null, d);
});
}
function install(name, completer, cb) {
var markerIn = '###-begin-' + name + '-completion-###',
markerOut = '###-end-' + name + '-completion-###';
var rc, scriptOutput;
readRc(completer, function(err, file) {
if(err) return cb(err);
var part = file.split(markerIn)[1];
if(part) {
return cb(null, ' ✗ ' + completer + ' tab-completion has been already installed. Do nothing.');
}
rc = file;
next();
});
script(name, completer, function(err, file) {
scriptOutput = file;
next();
});
function next() {
if(!rc || !scriptOutput) return;
writeRc(rc + scriptOutput, function(err) {
if(err) return cb(err);
return cb(null, ' ✓ ' + completer + ' tab-completion installed.');
});
}
}
function uninstall(name, completer, cb) {
var markerIn = '\n\n###-begin-' + name + '-completion-###',
markerOut = '###-end-' + name + '-completion-###\n';
readRc(completer, function(err, file) {
if(err) return cb(err);
var part = file.split(markerIn)[1];
if(!part) {
return cb(null, ' ✗ ' + completer + ' tab-completion has been already uninstalled. Do nothing.');
}
part = markerIn + part.split(markerOut)[0] + markerOut;
writeRc(file.replace(part, ''), function(err) {
if(err) return cb(err);
return cb(null, ' ✓ ' + completer + ' tab-completion uninstalled.');
});
});
}
function readRc(completer, cb) {
var file = '.' + process.env.SHELL.match(/\/bin\/(\w+)/)[1] + 'rc',
filepath = pth.join(process.env.HOME, file);
fs.lstat(filepath, function (err, stats) {
if(err) return cb(new Error("No " + file + " file. You'll have to run instead: " + completer + " completion >> ~/" + file));
fs.readFile(filepath, 'utf8', cb);
});
}
function writeRc(content, cb) {
var file = '.' + process.env.SHELL.match(/\/bin\/(\w+)/)[1] + 'rc',
filepath = pth.join(process.env.HOME, file);
fs.lstat(filepath, function (err, stats) {
if(err) return cb(new Error("No " + file + " file. You'll have to run instead: " + completer + " completion >> ~/" + file));
fs.writeFile(filepath, content, cb);
});
}
function installed (marker, completer, cb) {
readRc(completer, function(err, file) {
if(err) return cb(err);
var installed = file.match(marker);
return cb(!!installed);
});
}
function parseEnv() {
var args = process.argv.slice(2),
complete = args[0] === 'completion';
return {
args: args,
complete: complete,
install: complete && args[1] === 'install',
uninstall: complete && args[1] === 'uninstall',
words: +process.env.COMP_CWORD,
point: +process.env.COMP_POINT,
line: process.env.COMP_LINE
}
};

40
api.hyungi.net/node_modules/pm2/lib/completion.sh generated vendored Normal file
View File

@@ -0,0 +1,40 @@
###-begin-pm2-completion-###
### credits to npm for the completion file model
#
# Installation: pm2 completion >> ~/.bashrc (or ~/.zshrc)
#
COMP_WORDBREAKS=${COMP_WORDBREAKS/=/}
COMP_WORDBREAKS=${COMP_WORDBREAKS/@/}
export COMP_WORDBREAKS
if type complete &>/dev/null; then
_pm2_completion () {
local si="$IFS"
IFS=$'\n' COMPREPLY=($(COMP_CWORD="$COMP_CWORD" \
COMP_LINE="$COMP_LINE" \
COMP_POINT="$COMP_POINT" \
pm2 completion -- "${COMP_WORDS[@]}" \
2>/dev/null)) || return $?
IFS="$si"
}
complete -o default -F _pm2_completion pm2
elif type compctl &>/dev/null; then
_pm2_completion () {
local cword line point words si
read -Ac words
read -cn cword
let cword-=1
read -l line
read -ln point
si="$IFS"
IFS=$'\n' reply=($(COMP_CWORD="$cword" \
COMP_LINE="$line" \
COMP_POINT="$point" \
pm2 completion -- "${words[@]}" \
2>/dev/null)) || return $?
IFS="$si"
}
compctl -K _pm2_completion + -f + pm2
fi
###-end-pm2-completion-###

36
api.hyungi.net/node_modules/pm2/lib/motd generated vendored Normal file
View File

@@ -0,0 +1,36 @@
-------------
__/\\\\\\\\\\\\\____/\\\\____________/\\\\____/\\\\\\\\\_____
_\/\\\/////////\\\_\/\\\\\\________/\\\\\\__/\\\///////\\\___
_\/\\\_______\/\\\_\/\\\//\\\____/\\\//\\\_\///______\//\\\__
_\/\\\\\\\\\\\\\/__\/\\\\///\\\/\\\/_\/\\\___________/\\\/___
_\/\\\/////////____\/\\\__\///\\\/___\/\\\________/\\\//_____
_\/\\\_____________\/\\\____\///_____\/\\\_____/\\\//________
_\/\\\_____________\/\\\_____________\/\\\___/\\\/___________
_\/\\\_____________\/\\\_____________\/\\\__/\\\\\\\\\\\\\\\_
_\///______________\///______________\///__\///////////////__
Runtime Edition
PM2 is a Production Process Manager for Node.js applications
with a built-in Load Balancer.
Start and Daemonize any application:
$ pm2 start app.js
Load Balance 4 instances of api.js:
$ pm2 start api.js -i 4
Monitor in production:
$ pm2 monitor
Make pm2 auto-boot at server restart:
$ pm2 startup
To go further checkout:
http://pm2.io/
-------------

View File

@@ -0,0 +1,7 @@
FROM anapsix/alpine-java:latest
RUN apk update && apk add git && rm -rf /var/cache/apk/*
RUN npm install pm2@next -g
RUN mkdir -p /var/app
WORKDIR /var/app

View File

@@ -0,0 +1,8 @@
FROM keymetrics/pm2:latest
RUN mkdir -p /var/app
WORKDIR /var/app
COPY ./package.json /var/app
RUN npm install

View File

@@ -0,0 +1,7 @@
FROM anapsix/alpine-ruby:latest
RUN apk update && apk add git && rm -rf /var/cache/apk/*
RUN npm install pm2@next -g
RUN mkdir -p /var/app
WORKDIR /var/app

View File

@@ -0,0 +1,24 @@
const config = {
apps : [{
script: 'index.js',
watch: '.'
}, {
script: './service-worker/',
watch: ['./service-worker']
}],
deploy : {
production : {
user : 'SSH_USERNAME',
host : 'SSH_HOSTMACHINE',
ref : 'origin/master',
repo : 'GIT_REPOSITORY',
path : 'DESTINATION_PATH',
'pre-deploy-local': '',
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
'pre-setup': ''
}
}
};
export default config;

View File

@@ -0,0 +1,8 @@
const config = {
apps : [{
name : "app1",
script : "./app.js"
}]
}
export default config;

View File

@@ -0,0 +1,6 @@
module.exports = {
apps : [{
name : "app1",
script : "./app.js"
}]
}

View File

@@ -0,0 +1,22 @@
module.exports = {
apps : [{
script: 'index.js',
watch: '.'
}, {
script: './service-worker/',
watch: ['./service-worker']
}],
deploy : {
production : {
user : 'SSH_USERNAME',
host : 'SSH_HOSTMACHINE',
ref : 'origin/master',
repo : 'GIT_REPOSITORY',
path : 'DESTINATION_PATH',
'pre-deploy-local': '',
'post-deploy' : 'npm install && pm2 reload ecosystem.config.js --env production',
'pre-setup': ''
}
}
};

View File

@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>com.PM2</string>
<key>UserName</key>
<string>%USER%</string>
<key>KeepAlive</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/bin/sh</string>
<string>-c</string>
<string>%PM2_PATH% resurrect</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>OnDemand</key>
<false/>
<key>LaunchOnlyOnce</key>
<true/>
<key>EnvironmentVariables</key>
<dict>
<key>PATH</key>
<string>%NODE_PATH%</string>
<key>PM2_HOME</key>
<string>%HOME_PATH%</string>
</dict>
<key>StandardErrorPath</key>
<string>/tmp/com.PM2.err</string>
<key>StandardOutPath</key>
<string>/tmp/com.PM2.out</string>
</dict>
</plist>

View File

@@ -0,0 +1,52 @@
#!/sbin/openrc-run
# Copyright 2013-2022 the PM2 project authors. All rights reserved.
# Init script automatically generated by pm2 startup
description="Production process manager for Node.js apps with a built-in load balancer."
extra_started_commands="reload"
PM2="%PM2_PATH%"
user=${PM2_USER:-%USER%}
export PM2_HOME=$(eval echo ~${user})"/.pm2/"
# Options for start-stop-daemon (default start function)
command=${PM2}
command_user=${user}
command_args="resurrect"
pidfile=${PM2_HOME}/pm2.pid
run_pm2_as_user() {
einfo "${PM2} $@"
eval su -l ${user} -c \'${PM2} $@\'
}
depend() {
need net
need localmount
after bootmisc
}
start_post() {
if [ "${user}" == "root" ]; then
ewarn "PM2: Better run this daemon as a non root user. To set this user create"
ewarn "PM2: /etc/conf.d/pm2 file and define 'PM2_USER=user' there."
ewarn "PM2: Note user MUST have home directory for PM2 logs/state/etc..."
fi
einfo "PM2: Process Manager started. To start services run:"
einfo "PM2: # su -l ${user} -c '$PM2 start /path/to/app'"
}
stop() {
ebegin "Stopping PM2 process manager..."
run_pm2_as_user dump
run_pm2_as_user kill
eend $?
}
reload() {
ebegin "Reloading pm2"
run_pm2_as_user reload all
eend $?
}
# vim: ts=4

View File

@@ -0,0 +1,86 @@
#!/bin/bash
#
# pm2 Process manager for NodeJS
#
# chkconfig: 345 80 20
#
# description: PM2 next gen process manager for Node.js
# processname: pm2
#
### BEGIN INIT INFO
# Provides: pm2
# Required-Start: $local_fs $remote_fs
# Required-Stop: $local_fs $remote_fs
# Should-Start: $network
# Should-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: PM2 init script
# Description: PM2 is the next gen process manager for Node.js
### END INIT INFO
NAME=pm2
PM2=%PM2_PATH%
USER=%USER%
export PATH=%NODE_PATH%:$PATH
export PM2_HOME="%HOME_PATH%"
lockfile="/var/lock/subsys/pm2-init.sh"
super() {
su - $USER -c "PATH=$PATH; PM2_HOME=$PM2_HOME $*"
}
start() {
echo "Starting $NAME"
super $PM2 resurrect
retval=$?
[ $retval -eq 0 ] && touch $lockfile
}
stop() {
echo "Stopping $NAME"
super $PM2 kill
rm -f $lockfile
}
restart() {
echo "Restarting $NAME"
stop
start
}
reload() {
echo "Reloading $NAME"
super $PM2 reload all
}
status() {
echo "Status for $NAME:"
super $PM2 list
RETVAL=$?
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
reload)
reload
;;
*)
echo "Usage: {start|stop|status|restart|reload}"
exit 1
;;
esac
exit $RETVAL

View File

@@ -0,0 +1,41 @@
#!/bin/sh
#
# from /usr/ports/infrastructure/templates/rc.template
daemon="/usr/local/bin/pm2"
#daemon_flags=
#daemon_rtable=0
#daemon_timeout="30"
daemon_user="%USER%"
. /etc/rc.d/rc.subr
pexp="node: PM2.*God Daemon.*"
#rc_bg= # (undefined)
#rc_reload= # (undefined)
#rc_usercheck=YES
#rc_pre() {
#}
rc_start() {
${rcexec} "${daemon} ${daemon_flags} resurrect"
}
#rc_check() {
# pgrep -T "${daemon_rtable}" -q -xf "${pexp}"
#}
rc_reload() {
${rcexec} "${daemon} reload all"
#pkill -HUP -T "${daemon_rtable}" -xf "${pexp}"
}
#rc_stop() {
# pkill -T "${daemon_rtable}" -xf "${pexp}"
#}
#rc_post() {
#}
rc_cmd $1

View File

@@ -0,0 +1,44 @@
#!/bin/sh
# PROVIDE: pm2
# REQUIRE: LOGIN
# KEYWORD: shutdown
. /etc/rc.subr
name="%SERVICE_NAME%"
rcvar="%SERVICE_NAME%_enable"
start_cmd="pm2_start"
stop_cmd="pm2_stop"
reload_cmd="pm2_reload"
status_cmd="pm2_status"
extra_commands="reload status"
pm2()
{
env PATH="$PATH:%NODE_PATH%" PM2_HOME="%HOME_PATH%" su -m "%USER%" -c "%PM2_PATH% $*"
}
pm2_start()
{
pm2 resurrect
}
pm2_stop()
{
pm2 kill
}
pm2_reload()
{
pm2 reload all
}
pm2_status()
{
pm2 list
}
load_rc_config $name
run_rc_command "$1"

View File

@@ -0,0 +1,43 @@
<?xml version="1.0"?>
<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
<service_bundle type="manifest" name="%SERVICE_NAME%">
<service name="application/%SERVICE_NAME%" type="service" version="1">
<create_default_instance enabled="false"/>
<single_instance/>
<dependency name="network" grouping="require_all" restart_on="error" type="service">
<service_fmri value="svc:/milestone/network:default"/>
</dependency>
<dependency name="filesystem" grouping="require_all" restart_on="error" type="service">
<service_fmri value="svc:/system/filesystem/local"/>
</dependency>
<method_context>
<method_environment>
<envvar name='PATH' value="%NODE_PATH%:/usr/local/sbin:/usr/local/bin:/opt/local/sbin:/opt/local/bin:/usr/sbin:/usr/bin:/sbin"/>
<envvar name='PM2_HOME' value="%HOME_PATH%"/>
</method_environment>
</method_context>
<exec_method type="method" name="start" exec="%PM2_PATH% resurrect" timeout_seconds="60"/>
<exec_method type="method" name="refresh" exec="%PM2_PATH% reload all" timeout_seconds="60"/>
<exec_method type="method" name="stop" exec="%PM2_PATH% kill" timeout_seconds="60"/>
<property_group name="startd" type="framework">
<propval name="duration" type="astring" value="contract"/>
<propval name="ignore_error" type="astring" value="core,signal"/>
</property_group>
<property_group name="application" type="application"></property_group>
<stability value="Evolving"/>
<template>
<common_name>
<loctext xml:lang="C">
PM2 process manager
</loctext>
</common_name>
</template>
</service>
</service_bundle>

View File

@@ -0,0 +1,22 @@
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network-online.target
Restart=on-failure
[Service]
Type=forking
User=%USER%
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=%NODE_PATH%:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=%HOME_PATH%
PIDFile=%HOME_PATH%/pm2.pid
ExecStart=%PM2_PATH% resurrect
ExecReload=%PM2_PATH% reload all
ExecStop=%PM2_PATH% kill
[Install]
WantedBy=network-online.target

View File

@@ -0,0 +1,22 @@
[Unit]
Description=PM2 process manager
Documentation=https://pm2.keymetrics.io/
After=network.target
[Service]
Type=forking
User=%USER%
LimitNOFILE=infinity
LimitNPROC=infinity
LimitCORE=infinity
Environment=PATH=%NODE_PATH%:/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
Environment=PM2_HOME=%HOME_PATH%
PIDFile=%HOME_PATH%/pm2.pid
Restart=on-failure
ExecStart=%PM2_PATH% resurrect
ExecReload=%PM2_PATH% reload all
ExecStop=%PM2_PATH% kill
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,103 @@
#!/bin/bash
### BEGIN INIT INFO
# Provides: pm2
# Required-Start: $local_fs $remote_fs $network
# Required-Stop: $local_fs $remote_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: PM2 Init script
# Description: PM2 process manager
### END INIT INFO
NAME=pm2
PM2=%PM2_PATH%
USER=%USER%
DEFAULT=/etc/default/$NAME
export PATH=%NODE_PATH%:$PATH
export PM2_HOME="%HOME_PATH%"
# The following variables can be overwritten in $DEFAULT
# maximum number of open files
MAX_OPEN_FILES=
# overwrite settings from default file
if [ -f "$DEFAULT" ]; then
. "$DEFAULT"
fi
# set maximum open files if set
if [ -n "$MAX_OPEN_FILES" ]; then
ulimit -n $MAX_OPEN_FILES
fi
get_user_shell() {
local shell
shell=$(getent passwd "${1:-$(whoami)}" | cut -d: -f7 | sed -e 's/[[:space:]]*$//')
if [[ $shell == *"/sbin/nologin" ]] || [[ $shell == "/bin/false" ]] || [[ -z "$shell" ]];
then
shell="/bin/bash"
fi
echo "$shell"
}
super() {
local shell
shell=$(get_user_shell $USER)
su - "$USER" -s "$shell" -c "PATH=$PATH; PM2_HOME=$PM2_HOME $*"
}
start() {
echo "Starting $NAME"
super $PM2 resurrect
}
stop() {
super $PM2 kill
}
restart() {
echo "Restarting $NAME"
stop
start
}
reload() {
echo "Reloading $NAME"
super $PM2 reload all
}
status() {
echo "Status for $NAME:"
super $PM2 list
RETVAL=$?
}
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
restart
;;
reload)
reload
;;
force-reload)
reload
;;
*)
echo "Usage: {start|stop|status|restart|reload|force-reload}"
exit 1
;;
esac
exit $RETVAL

View File

@@ -0,0 +1,10 @@
%HOME_PATH%/pm2.log %HOME_PATH%/logs/*.log {
rotate 12
weekly
missingok
notifempty
compress
delaycompress
copytruncate
create 0640 %USER% %USER%
}

View File

@@ -0,0 +1,14 @@
# Basic HTTP Server and Cluster mode
In this boilerplate it will start an http server in cluster mode.
You can check the content of the ecosystem.config.js on how to start mutliple instances of the same HTTP application in order to get the most from your working system.
## Via CLI
Via CLI you can start any HTTP/TCP application in cluster mode with:
```bash
$ pm2 start api.js -i max
```

View File

@@ -0,0 +1,9 @@
var http = require('http');
var server = http.createServer(function(req, res) {
res.writeHead(200);
res.end('hey');
}).listen(process.env.PORT || 8000, function() {
console.log('App listening on port %d', server.address().port);
});

View File

@@ -0,0 +1,14 @@
module.exports = {
apps : [{
name: 'API',
script: 'api.js',
instances: 4,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};

View File

@@ -0,0 +1,11 @@
{
"name": "simple-http-server",
"version": "1.0.0",
"description": "Simple HTTP server that can be used in cluster mode",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

@@ -0,0 +1,45 @@
# pm2 custom metrics boilerplate
In this boilerplate you will discover a working example of custom metrics feature.
Metrics covered are:
- io.metric
- io.counter
- io.meter
- io.histogram
## What is Custom Metrics?
Custom metrics is a powerfull way to get more visibility from a running application. It will allow you to monitor in realtime the current value of variables, know the number of actions being processed, measure latency and much more.
Once you have plugged in some custom metrics you will be able to monitor their value in realtime with
`pm2 monit`
Or
`pm2 describe`
Or on the PM2+ Web interface
`pm2 open`
## Example
```javascript
const io = require('@pm2/io')
const currentReq = io.counter({
name: 'CM: Current Processing',
type: 'counter'
})
setInterval(() => {
currentReq.inc()
}, 1000)
```
## Documentation
https://doc.pm2.io/en/plus/guide/custom-metrics/

View File

@@ -0,0 +1,66 @@
const io = require('@pm2/io')
// Straight Metric
var user_count = 10
const users = io.metric({
name: 'CM: Realtime user',
value: () => {
return user_count
}
})
// or users.set(user_count)
// Counter (.inc() .dec())
const currentReq = io.counter({
name: 'CM: Current Processing',
type: 'counter'
})
setInterval(() => {
currentReq.inc()
}, 1000)
// Meter
const reqsec = io.meter({
name: 'CM: req/sec'
})
setInterval(() => {
reqsec.mark()
}, 100)
// Histogram
const latency = io.histogram({
name: 'CM: latency'
});
var latencyValue = 0;
setInterval(() => {
latencyValue = Math.round(Math.random() * 100);
latency.update(latencyValue);
}, 100)
////////////////////
// Custom Actions //
////////////////////
io.action('add user', (done) => {
user_count++
done({success:true})
})
io.action('remove user', (done) => {
user_count++
done({success:true})
})
io.action('with params', (arg, done) => {
console.log(arg)
done({success:arg})
})

View File

@@ -0,0 +1,12 @@
module.exports = {
apps : [{
name: 'Custom Metrics',
script: 'custom-metrics.js',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};

View File

@@ -0,0 +1,11 @@
{
"name": "pm2-plus-custom-metrics",
"version": "1.0.0",
"description": "Example that shows how to use pm2+ custom metrics",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

View File

@@ -0,0 +1,4 @@
# Managing a Python Application
On this boilerlate you will see how you can start a Python application with PM2.

View File

@@ -0,0 +1,7 @@
#!/usr/bin/python
import time
while 1:
print("Start : %s" % time.ctime())
print("second line")
time.sleep(1)

View File

@@ -0,0 +1,12 @@
module.exports = {
apps : [{
name: 'API',
script: 'echo.py',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};

View File

@@ -0,0 +1,11 @@
{
"name": "python-app",
"version": "1.0.0",
"description": "Example on how to manage a Python application with PM2",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}

247
api.hyungi.net/node_modules/pm2/lib/tools/Config.js generated vendored Normal file
View File

@@ -0,0 +1,247 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var util = require('util');
/**
* Validator of configured file / commander options.
*/
var Config = module.exports = {
_errMsgs: {
'require': '"%s" is required',
'type' : 'Expect "%s" to be a typeof %s, but now is %s',
'regex' : 'Verify "%s" with regex failed, %s',
'max' : 'The maximum of "%s" is %s, but now is %s',
'min' : 'The minimum of "%s" is %s, but now is %s'
},
/**
* Schema definition.
* @returns {exports|*}
*/
get schema(){
// Cache.
if (this._schema) {
return this._schema;
}
// Render aliases.
this._schema = require('../API/schema');
for (var k in this._schema) {
if (k.indexOf('\\') > 0) {
continue;
}
var aliases = [
k.split('_').map(function(n, i){
if (i != 0 && n && n.length > 1) {
return n[0].toUpperCase() + n.slice(1);
}
return n;
}).join('')
];
if (this._schema[k].alias && Array.isArray(this._schema[k].alias)) {
// If multiple aliases, merge
this._schema[k].alias.forEach(function(alias) {
aliases.splice(0, 0, alias);
});
}
else if (this._schema[k].alias)
aliases.splice(0, 0, this._schema[k].alias);
this._schema[k].alias = aliases;
}
return this._schema;
}
};
/**
* Filter / Alias options
*/
Config.filterOptions = function(cmd) {
var conf = {};
var schema = this.schema;
for (var key in schema) {
var aliases = schema[key].alias;
aliases && aliases.forEach(function(alias){
if (typeof(cmd[alias]) !== 'undefined') {
conf[key] || (conf[key] = cmd[alias]);
}
});
}
return conf;
};
/**
* Verify JSON configurations.
* @param {Object} json
* @returns {{errors: Array, config: {}}}
*/
Config.validateJSON = function(json){
// clone config
var conf = Object.assign({}, json),
res = {};
this._errors = [];
var regexKeys = {}, defines = this.schema;
for (var sk in defines) {
// Pick up RegExp keys.
if (sk.indexOf('\\') >= 0) {
regexKeys[sk] = false;
continue;
}
var aliases = defines[sk].alias;
aliases && aliases.forEach(function(alias){
conf[sk] || (conf[sk] = json[alias]);
})
var val = conf[sk];
delete conf[sk];
// Validate key-value pairs.
if (val === undefined ||
val === null ||
((val = this._valid(sk, val)) === null)) {
// If value is not defined
// Set default value (via schema.json)
if (typeof(defines[sk].default) !== 'undefined')
res[sk] = defines[sk].default;
continue;
}
//console.log(sk, val, val === null, val === undefined);
res[sk] = val;
}
// Validate RegExp values.
var hasRegexKey = false;
for (var k in regexKeys) {
hasRegexKey = true;
regexKeys[k] = new RegExp(k);
}
if (hasRegexKey) {
for (var k in conf) {
for (var rk in regexKeys) {
if (regexKeys[rk].test(k))
if (this._valid(k, conf[k], defines[rk])) {
res[k] = conf[k];
delete conf[k];
}
}
}
}
return {errors: this._errors, config: res};
};
/**
* Validate key-value pairs by specific schema
* @param {String} key
* @param {Mixed} value
* @param {Object} sch
* @returns {*}
* @private
*/
Config._valid = function(key, value, sch){
var sch = sch || this.schema[key],
scht = typeof sch.type == 'string' ? [sch.type] : sch.type;
// Required value.
var undef = typeof value == 'undefined';
if(this._error(sch.require && undef, 'require', key)){
return null;
}
// If undefined, make a break.
if (undef) {
return null;
}
// Wrap schema types.
scht = scht.map(function(t){
return '[object ' + t[0].toUpperCase() + t.slice(1) + ']'
});
// Typeof value.
var type = Object.prototype.toString.call(value), nt = '[object Number]';
// Auto parse Number
if (type != '[object Boolean]' && scht.indexOf(nt) >= 0 && !isNaN(value)) {
value = parseFloat(value);
type = nt;
}
// Verify types.
if (this._error(!~scht.indexOf(type), 'type', key, scht.join(' / '), type)) {
return null;
}
// Verify RegExp if exists.
if (this._error(type == '[object String]' && sch.regex && !(new RegExp(sch.regex)).test(value),
'regex', key, sch.desc || ('should match ' + sch.regex))) {
return null;
}
// Verify maximum / minimum of Number value.
if (type == '[object Number]') {
if (this._error(typeof sch.max != 'undefined' && value > sch.max, 'max', key, sch.max, value)) {
return null;
}
if (this._error(typeof sch.min != 'undefined' && value < sch.min, 'min', key, sch.min, value)) {
return null;
}
}
// If first type is Array, but current is String, try to split them.
if(scht.length > 1 && type != scht[0] && type == '[object String]'){
if(scht[0] == '[object Array]') {
// unfortunately, js does not support lookahead RegExp (/(?<!\\)\s+/) now (until next ver).
value = value.split(/([\w\-]+\="[^"]*")|([\w\-]+\='[^']*')|"([^"]*)"|'([^']*)'|\s/)
.filter(function(v){
return v && v.trim();
});
}
}
// Custom types: sbyte && stime.
if(sch.ext_type && type == '[object String]' && value.length >= 2) {
var seed = {
'sbyte': {
'G': 1024 * 1024 * 1024,
'M': 1024 * 1024,
'K': 1024
},
'stime': {
'h': 60 * 60 * 1000,
'm': 60 * 1000,
's': 1000
}
}[sch.ext_type];
if(seed){
value = parseFloat(value.slice(0, -1)) * (seed[value.slice(-1)]);
}
}
return value;
};
/**
* Wrap errors.
* @param {Boolean} possible A value indicates whether it is an error or not.
* @param {String} type
* @returns {*}
* @private
*/
Config._error = function(possible, type){
if (possible) {
var args = Array.prototype.slice.call(arguments);
args.splice(0, 2, this._errMsgs[type]);
this._errors && this._errors.push(util.format.apply(null, args));
}
return possible;
}

View File

@@ -0,0 +1,20 @@
'use strict';
function posix(path) {
return path.charAt(0) === '/';
}
function win32(path) {
// https://github.com/nodejs/node/blob/b3fcc245fb25539909ef1d5eaa01dbf92e168633/lib/path.js#L56
var splitDeviceRe = /^([a-zA-Z]:|[\\/]{2}[^\\/]+[\\/]+[^\\/]+)?([\\/])?([\s\S]*?)$/;
var result = splitDeviceRe.exec(path);
var device = result[1] || '';
var isUnc = Boolean(device && device.charAt(1) !== ':');
// UNC paths are always absolute
return Boolean(result[2] || isUnc);
}
module.exports = process.platform === 'win32' ? win32 : posix;
module.exports.posix = posix;
module.exports.win32 = win32;

View File

@@ -0,0 +1,101 @@
var fs = require('fs');
var path = require('path');
/*
options: {
utimes: false, // Boolean | Object, keep utimes if true
mode: false, // Boolean | Number, keep file mode if true
cover: true, // Boolean, cover if file exists
filter: true, // Boolean | Function, file filter
}
*/
function copydirSync(from, to, options) {
if (typeof options === 'function') {
options = {
filter: options
};
}
if(typeof options === 'undefined') options = {};
if(typeof options.cover === 'undefined') {
options.cover = true;
}
options.filter = typeof options.filter === 'function' ? options.filter : function(state, filepath, filename) {
return options.filter;
};
var stats = fs.lstatSync(from);
var statsname = stats.isDirectory() ? 'directory' :
stats.isFile() ? 'file' :
stats.isSymbolicLink() ? 'symbolicLink' :
'';
var valid = options.filter(statsname, from, path.dirname(from), path.basename(from));
if (statsname === 'directory' || statsname === 'symbolicLink') {
// Directory or SymbolicLink
if(valid) {
try {
fs.statSync(to);
} catch(err) {
if(err.code === 'ENOENT') {
fs.mkdirSync(to);
options.debug && console.log('>> ' + to);
} else {
throw err;
}
}
rewriteSync(to, options, stats);
if (statsname != 'symbolicLink')
listDirectorySync(from, to, options);
}
} else if(stats.isFile()) {
// File
if(valid) {
if(options.cover) {
writeFileSync(from, to, options, stats);
} else {
try {
fs.statSync(to);
} catch(err) {
if(err.code === 'ENOENT') {
writeFileSync(from, to, options, stats);
} else {
throw err;
}
}
}
}
} else {
throw new Error('stats invalid: '+ from);
}
};
function listDirectorySync(from, to, options) {
var files = fs.readdirSync(from);
copyFromArraySync(files, from, to, options);
}
function copyFromArraySync(files, from, to, options) {
if(files.length === 0) return true;
var f = files.shift();
copydirSync(path.join(from, f), path.join(to, f), options);
copyFromArraySync(files, from, to, options);
}
function writeFileSync(from, to, options, stats) {
fs.writeFileSync(to, fs.readFileSync(from, 'binary'), 'binary');
options.debug && console.log('>> ' + to);
rewriteSync(to, options, stats);
}
function rewriteSync(f, options, stats, callback) {
if(options.cover) {
var mode = options.mode === true ? stats.mode : options.mode;
var utimes = options.utimes === true ? {
atime: stats.atime,
mtime: stats.mtime
} : options.utimes;
mode && fs.chmodSync(f, mode);
utimes && fs.utimesSync(f, utimes.atime, utimes.mtime);
}
return true;
}
module.exports = copydirSync;

View File

@@ -0,0 +1,19 @@
const fs = require('fs');
const Path = require('path');
const deleteFolderRecursive = function(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach((file, index) => {
const curPath = Path.join(path, file);
if (fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};
module.exports = deleteFolderRecursive

View File

@@ -0,0 +1,74 @@
'use strict';
var path = require('path')
, fs = require('fs');
/**
* Attempt to somewhat safely parse the JSON.
*
* @param {String} data JSON blob that needs to be parsed.
* @returns {Object|false} Parsed JSON or false.
* @api private
*/
function parse(data) {
data = data.toString('utf-8');
//
// Remove a possible UTF-8 BOM (byte order marker) as this can lead to parse
// values when passed in to the JSON.parse.
//
if (data.charCodeAt(0) === 0xFEFF) data = data.slice(1);
try { return JSON.parse(data); }
catch (e) { return false; }
}
/**
* Find package.json files.
*
* @param {String|Object} root The root directory we should start searching in.
* @returns {Object} Iterator interface.
* @api public
*/
module.exports = function find(root) {
root = root || process.cwd();
if (typeof root !== "string") {
if (typeof root === "object" && typeof root.filename === 'string') {
root = root.filename;
} else {
throw new Error("Must pass a filename string or a module object to finder");
}
}
return {
/**
* Return the parsed package.json that we find in a parent folder.
*
* @returns {Object} Value, filename and indication if the iteration is done.
* @api public
*/
next: function next() {
if (root.match(/^(\w:\\|\/)$/)) return {
value: undefined,
filename: undefined,
done: true
};
var file = path.join(root, 'package.json')
, data;
root = path.resolve(root, '..');
if (fs.existsSync(file) && (data = parse(fs.readFileSync(file)))) {
data.__path = file;
return {
value: data,
filename: file,
done: false
};
}
return next();
}
};
};

72
api.hyungi.net/node_modules/pm2/lib/tools/fmt.js generated vendored Normal file
View File

@@ -0,0 +1,72 @@
// --------------------------------------------------------------------------------------------------------------------
//
// fmt.js - Command line output formatting.
//
// Copyright (c) 2012 Andrew Chilton - http://chilts.org/
// Written by Andrew Chilton <andychilton@gmail.com>
//
// License: http://opensource.org/licenses/MIT
//
// --------------------------------------------------------------------------------------------------------------------
var util = require('util');
// --------------------------------------------------------------------------------------------------------------------
var sep = '===============================================================================';
var line = '-------------------------------------------------------------------------------';
var field = ' ';
// --------------------------------------------------------------------------------------------------------------------
// separator
module.exports.separator = function() {
console.log(sep);
};
// alias the above
module.exports.sep = module.exports.separator;
// line
module.exports.line = function() {
console.log(line);
};
// title
module.exports.title = function(title) {
var out = '--- ' + title + ' ';
out += line.substr(out.length);
console.log(out);
};
// field
module.exports.field = function(key, value) {
console.log('' + key + field.substr(key.length) + ' : ' + value);
};
// subfield
module.exports.subfield = function(key, value) {
console.log('- ' + key + field.substr(key.length + 2) + ' : ' + value);
};
// list item
module.exports.li = function(msg) {
console.log('* ' + msg);
};
// dump
module.exports.dump = function(data, name) {
if ( name ) {
console.log(name + ' :', util.inspect(data, false, null, true));
}
else {
console.log(util.inspect(data, false, null, true));
}
};
// msg
module.exports.msg = function(msg) {
console.log(msg);
};
// --------------------------------------------------------------------------------------------------------------------

View File

@@ -0,0 +1,94 @@
/**
* Copyright 2013-2022 the PM2 project authors. All rights reserved.
* Use of this source code is governed by a license that
* can be found in the LICENSE file.
*/
var fs = require('fs');
var max_bytes = 512;
module.exports = function(bytes, size) {
// Read the file with no encoding for raw buffer access.
if (size === undefined) {
var file = bytes;
try {
if(!fs.statSync(file).isFile()) return false;
} catch (err) {
// otherwise continue on
}
var descriptor = fs.openSync(file, 'r');
try {
bytes = Buffer.alloc(max_bytes);
size = fs.readSync(descriptor, bytes, 0, bytes.length, 0);
} finally {
fs.closeSync(descriptor);
}
}
// async version has a function instead of a `size`
else if (typeof size === "function") {
var file = bytes, callback = size;
fs.stat(file, function(err, stat) {
if (err || !stat.isFile()) return callback(null, false);
fs.open(file, 'r', function(err, descriptor){
if (err) return callback(err);
var bytes = Buffer.alloc(max_bytes);
// Read the file with no encoding for raw buffer access.
fs.read(descriptor, bytes, 0, bytes.length, 0, function(err, size, bytes){
fs.close(descriptor, function(err2){
if (err || err2)
return callback(err || err2);
return callback(null, isBinaryCheck(bytes, size));
});
});
});
});
}
return isBinaryCheck(bytes, size);
}
function isBinaryCheck(bytes, size) {
if (size === 0)
return false;
var suspicious_bytes = 0;
var total_bytes = Math.min(size, max_bytes);
if (size >= 3 && bytes[0] == 0xEF && bytes[1] == 0xBB && bytes[2] == 0xBF) {
// UTF-8 BOM. This isn't binary.
return false;
}
for (var i = 0; i < total_bytes; i++) {
if (bytes[i] === 0) { // NULL byte--it's binary!
return true;
}
else if ((bytes[i] < 7 || bytes[i] > 14) && (bytes[i] < 32 || bytes[i] > 127)) {
// UTF-8 detection
if (bytes[i] > 193 && bytes[i] < 224 && i + 1 < total_bytes) {
i++;
if (bytes[i] > 127 && bytes[i] < 192) {
continue;
}
}
else if (bytes[i] > 223 && bytes[i] < 240 && i + 2 < total_bytes) {
i++;
if (bytes[i] > 127 && bytes[i] < 192 && bytes[i + 1] > 127 && bytes[i + 1] < 192) {
i++;
continue;
}
}
suspicious_bytes++;
// Read at least 32 bytes before making a decision
if (i > 32 && (suspicious_bytes * 100) / total_bytes > 10) {
return true;
}
}
}
if ((suspicious_bytes * 100) / total_bytes > 10) {
return true;
}
return false;
}

752
api.hyungi.net/node_modules/pm2/lib/tools/json5.js generated vendored Normal file
View File

@@ -0,0 +1,752 @@
// json5.js
// Modern JSON. See README.md for details.
//
// This file is based directly off of Douglas Crockford's json_parse.js:
// https://github.com/douglascrockford/JSON-js/blob/master/json_parse.js
var JSON5 = (typeof exports === 'object' ? exports : {});
JSON5.parse = (function () {
"use strict";
// This is a function that can parse a JSON5 text, producing a JavaScript
// data structure. It is a simple, recursive descent parser. It does not use
// eval or regular expressions, so it can be used as a model for implementing
// a JSON5 parser in other languages.
// We are defining the function inside of another function to avoid creating
// global variables.
var at, // The index of the current character
ch, // The current character
escapee = {
"'": "'",
'"': '"',
'\\': '\\',
'/': '/',
'\n': '', // Replace escaped newlines in strings w/ empty string
b: '\b',
f: '\f',
n: '\n',
r: '\r',
t: '\t'
},
ws = [
' ',
'\t',
'\r',
'\n',
'\v',
'\f',
'\xA0',
'\uFEFF'
],
text,
error = function (m) {
// Call error when something is wrong.
var error = new SyntaxError();
error.message = m;
error.at = at;
error.text = text;
throw error;
},
next = function (c) {
// If a c parameter is provided, verify that it matches the current character.
if (c && c !== ch) {
error("Expected '" + c + "' instead of '" + ch + "'");
}
// Get the next character. When there are no more characters,
// return the empty string.
ch = text.charAt(at);
at += 1;
return ch;
},
peek = function () {
// Get the next character without consuming it or
// assigning it to the ch varaible.
return text.charAt(at);
},
identifier = function () {
// Parse an identifier. Normally, reserved words are disallowed here, but we
// only use this for unquoted object keys, where reserved words are allowed,
// so we don't check for those here. References:
// - http://es5.github.com/#x7.6
// - https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Core_Language_Features#Variables
// - http://docstore.mik.ua/orelly/webprog/jscript/ch02_07.htm
var key = ch;
// Identifiers must start with a letter, _ or $.
if ((ch !== '_' && ch !== '$') &&
(ch < 'a' || ch > 'z') &&
(ch < 'A' || ch > 'Z')) {
error("Bad identifier");
}
// Subsequent characters can contain digits.
while (next() && (
ch === '_' || ch === '$' ||
(ch >= 'a' && ch <= 'z') ||
(ch >= 'A' && ch <= 'Z') ||
(ch >= '0' && ch <= '9'))) {
key += ch;
}
return key;
},
number = function () {
// Parse a number value.
var number,
sign = '',
string = '',
base = 10;
if (ch === '-' || ch === '+') {
sign = ch;
next(ch);
}
// support for Infinity (could tweak to allow other words):
if (ch === 'I') {
number = word();
if (typeof number !== 'number' || isNaN(number)) {
error('Unexpected word for number');
}
return (sign === '-') ? -number : number;
}
// support for NaN
if (ch === 'N' ) {
number = word();
if (!isNaN(number)) {
error('expected word to be NaN');
}
// ignore sign as -NaN also is NaN
return number;
}
if (ch === '0') {
string += ch;
next();
if (ch === 'x' || ch === 'X') {
string += ch;
next();
base = 16;
} else if (ch >= '0' && ch <= '9') {
error('Octal literal');
}
}
switch (base) {
case 10:
while (ch >= '0' && ch <= '9' ) {
string += ch;
next();
}
if (ch === '.') {
string += '.';
while (next() && ch >= '0' && ch <= '9') {
string += ch;
}
}
if (ch === 'e' || ch === 'E') {
string += ch;
next();
if (ch === '-' || ch === '+') {
string += ch;
next();
}
while (ch >= '0' && ch <= '9') {
string += ch;
next();
}
}
break;
case 16:
while (ch >= '0' && ch <= '9' || ch >= 'A' && ch <= 'F' || ch >= 'a' && ch <= 'f') {
string += ch;
next();
}
break;
}
if(sign === '-') {
number = -string;
} else {
number = +string;
}
if (!isFinite(number)) {
error("Bad number");
} else {
return number;
}
},
string = function () {
// Parse a string value.
var hex,
i,
string = '',
delim, // double quote or single quote
uffff;
// When parsing for string values, we must look for ' or " and \ characters.
if (ch === '"' || ch === "'") {
delim = ch;
while (next()) {
if (ch === delim) {
next();
return string;
} else if (ch === '\\') {
next();
if (ch === 'u') {
uffff = 0;
for (i = 0; i < 4; i += 1) {
hex = parseInt(next(), 16);
if (!isFinite(hex)) {
break;
}
uffff = uffff * 16 + hex;
}
string += String.fromCharCode(uffff);
} else if (ch === '\r') {
if (peek() === '\n') {
next();
}
} else if (typeof escapee[ch] === 'string') {
string += escapee[ch];
} else {
break;
}
} else if (ch === '\n') {
// unescaped newlines are invalid; see:
// https://github.com/aseemk/json5/issues/24
// invalid unescaped chars?
break;
} else {
string += ch;
}
}
}
error("Bad string");
},
inlineComment = function () {
// Skip an inline comment, assuming this is one. The current character should
// be the second / character in the // pair that begins this inline comment.
// To finish the inline comment, we look for a newline or the end of the text.
if (ch !== '/') {
error("Not an inline comment");
}
do {
next();
if (ch === '\n' || ch === '\r') {
next();
return;
}
} while (ch);
},
blockComment = function () {
// Skip a block comment, assuming this is one. The current character should be
// the * character in the /* pair that begins this block comment.
// To finish the block comment, we look for an ending */ pair of characters,
// but we also watch for the end of text before the comment is terminated.
if (ch !== '*') {
error("Not a block comment");
}
do {
next();
while (ch === '*') {
next('*');
if (ch === '/') {
next('/');
return;
}
}
} while (ch);
error("Unterminated block comment");
},
comment = function () {
// Skip a comment, whether inline or block-level, assuming this is one.
// Comments always begin with a / character.
if (ch !== '/') {
error("Not a comment");
}
next('/');
if (ch === '/') {
inlineComment();
} else if (ch === '*') {
blockComment();
} else {
error("Unrecognized comment");
}
},
white = function () {
// Skip whitespace and comments.
// Note that we're detecting comments by only a single / character.
// This works since regular expressions are not valid JSON(5), but this will
// break if there are other valid values that begin with a / character!
while (ch) {
if (ch === '/') {
comment();
} else if (ws.indexOf(ch) >= 0) {
next();
} else {
return;
}
}
},
word = function () {
// true, false, or null.
switch (ch) {
case 't':
next('t');
next('r');
next('u');
next('e');
return true;
case 'f':
next('f');
next('a');
next('l');
next('s');
next('e');
return false;
case 'n':
next('n');
next('u');
next('l');
next('l');
return null;
case 'I':
next('I');
next('n');
next('f');
next('i');
next('n');
next('i');
next('t');
next('y');
return Infinity;
case 'N':
next( 'N' );
next( 'a' );
next( 'N' );
return NaN;
}
error("Unexpected '" + ch + "'");
},
value, // Place holder for the value function.
array = function () {
// Parse an array value.
var array = [];
if (ch === '[') {
next('[');
white();
while (ch) {
if (ch === ']') {
next(']');
return array; // Potentially empty array
}
// ES5 allows omitting elements in arrays, e.g. [,] and
// [,null]. We don't allow this in JSON5.
if (ch === ',') {
error("Missing array element");
} else {
array.push(value());
}
white();
// If there's no comma after this value, this needs to
// be the end of the array.
if (ch !== ',') {
next(']');
return array;
}
next(',');
white();
}
}
error("Bad array");
},
object = function () {
// Parse an object value.
var key,
object = {};
if (ch === '{') {
next('{');
white();
while (ch) {
if (ch === '}') {
next('}');
return object; // Potentially empty object
}
// Keys can be unquoted. If they are, they need to be
// valid JS identifiers.
if (ch === '"' || ch === "'") {
key = string();
} else {
key = identifier();
}
white();
next(':');
object[key] = value();
white();
// If there's no comma after this pair, this needs to be
// the end of the object.
if (ch !== ',') {
next('}');
return object;
}
next(',');
white();
}
}
error("Bad object");
};
value = function () {
// Parse a JSON value. It could be an object, an array, a string, a number,
// or a word.
white();
switch (ch) {
case '{':
return object();
case '[':
return array();
case '"':
case "'":
return string();
case '-':
case '+':
case '.':
return number();
default:
return ch >= '0' && ch <= '9' ? number() : word();
}
};
// Return the json_parse function. It will have access to all of the above
// functions and variables.
return function (source, reviver) {
var result;
text = String(source);
at = 0;
ch = ' ';
result = value();
white();
if (ch) {
error("Syntax error");
}
// If there is a reviver function, we recursively walk the new structure,
// passing each name/value pair to the reviver function for possible
// transformation, starting with a temporary root object that holds the result
// in an empty key. If there is not a reviver function, we simply return the
// result.
return typeof reviver === 'function' ? (function walk(holder, key) {
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}({'': result}, '')) : result;
};
}());
// JSON5 stringify will not quote keys where appropriate
JSON5.stringify = function (obj, replacer, space) {
if (replacer && (typeof(replacer) !== "function" && !isArray(replacer))) {
throw new Error('Replacer must be a function or an array');
}
var getReplacedValueOrUndefined = function(holder, key, isTopLevel) {
var value = holder[key];
// Replace the value with its toJSON value first, if possible
if (value && value.toJSON && typeof value.toJSON === "function") {
value = value.toJSON();
}
// If the user-supplied replacer if a function, call it. If it's an array, check objects' string keys for
// presence in the array (removing the key/value pair from the resulting JSON if the key is missing).
if (typeof(replacer) === "function") {
return replacer.call(holder, key, value);
} else if(replacer) {
if (isTopLevel || isArray(holder) || replacer.indexOf(key) >= 0) {
return value;
} else {
return undefined;
}
} else {
return value;
}
};
function isWordChar(char) {
return (char >= 'a' && char <= 'z') ||
(char >= 'A' && char <= 'Z') ||
(char >= '0' && char <= '9') ||
char === '_' || char === '$';
}
function isWordStart(char) {
return (char >= 'a' && char <= 'z') ||
(char >= 'A' && char <= 'Z') ||
char === '_' || char === '$';
}
function isWord(key) {
if (typeof key !== 'string') {
return false;
}
if (!isWordStart(key[0])) {
return false;
}
var i = 1, length = key.length;
while (i < length) {
if (!isWordChar(key[i])) {
return false;
}
i++;
}
return true;
}
// export for use in tests
JSON5.isWord = isWord;
// polyfills
function isArray(obj) {
if (Array.isArray) {
return Array.isArray(obj);
} else {
return Object.prototype.toString.call(obj) === '[object Array]';
}
}
function isDate(obj) {
return Object.prototype.toString.call(obj) === '[object Date]';
}
isNaN = isNaN || function(val) {
return typeof val === 'number' && val !== val;
};
var objStack = [];
function checkForCircular(obj) {
for (var i = 0; i < objStack.length; i++) {
if (objStack[i] === obj) {
throw new TypeError("Converting circular structure to JSON");
}
}
}
function makeIndent(str, num, noNewLine) {
if (!str) {
return "";
}
// indentation no more than 10 chars
if (str.length > 10) {
str = str.substring(0, 10);
}
var indent = noNewLine ? "" : "\n";
for (var i = 0; i < num; i++) {
indent += str;
}
return indent;
}
var indentStr;
if (space) {
if (typeof space === "string") {
indentStr = space;
} else if (typeof space === "number" && space >= 0) {
indentStr = makeIndent(" ", space, true);
} else {
// ignore space parameter
}
}
// Copied from Crokford's implementation of JSON
// See https://github.com/douglascrockford/JSON-js/blob/e39db4b7e6249f04a195e7dd0840e610cc9e941e/json2.js#L195
// Begin
var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
function escapeString(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string' ?
c :
'\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
// End
function internalStringify(holder, key, isTopLevel) {
var buffer, res;
// Replace the value, if necessary
var obj_part = getReplacedValueOrUndefined(holder, key, isTopLevel);
if (obj_part && !isDate(obj_part)) {
// unbox objects
// don't unbox dates, since will turn it into number
obj_part = obj_part.valueOf();
}
switch(typeof obj_part) {
case "boolean":
return obj_part.toString();
case "number":
if (isNaN(obj_part) || !isFinite(obj_part)) {
return "null";
}
return obj_part.toString();
case "string":
return escapeString(obj_part.toString());
case "object":
if (obj_part === null) {
return "null";
} else if (isArray(obj_part)) {
checkForCircular(obj_part);
buffer = "[";
objStack.push(obj_part);
for (var i = 0; i < obj_part.length; i++) {
res = internalStringify(obj_part, i, false);
buffer += makeIndent(indentStr, objStack.length);
if (res === null || typeof res === "undefined") {
buffer += "null";
} else {
buffer += res;
}
if (i < obj_part.length-1) {
buffer += ",";
} else if (indentStr) {
buffer += "\n";
}
}
objStack.pop();
buffer += makeIndent(indentStr, objStack.length, true) + "]";
} else {
checkForCircular(obj_part);
buffer = "{";
var nonEmpty = false;
objStack.push(obj_part);
for (var prop in obj_part) {
if (obj_part.hasOwnProperty(prop)) {
var value = internalStringify(obj_part, prop, false);
isTopLevel = false;
if (typeof value !== "undefined" && value !== null) {
buffer += makeIndent(indentStr, objStack.length);
nonEmpty = true;
var key = isWord(prop) ? prop : escapeString(prop);
buffer += key + ":" + (indentStr ? ' ' : '') + value + ",";
}
}
}
objStack.pop();
if (nonEmpty) {
buffer = buffer.substring(0, buffer.length-1) + makeIndent(indentStr, objStack.length) + "}";
} else {
buffer = '{}';
}
}
return buffer;
default:
// functions and undefined should be ignored
return undefined;
}
}
// special case...when undefined is used inside of
// a compound object/array, return null.
// but when top-level, return undefined
var topLevelHolder = {"":obj};
if (obj === undefined) {
return getReplacedValueOrUndefined(topLevelHolder, '', true);
}
return internalStringify(topLevelHolder, '', true);
};

63
api.hyungi.net/node_modules/pm2/lib/tools/open.js generated vendored Normal file
View File

@@ -0,0 +1,63 @@
var exec = require('child_process').exec
, path = require('path')
;
/**
* open a file or uri using the default application for the file type.
*
* @return {ChildProcess} - the child process object.
* @param {string} target - the file/uri to open.
* @param {string} appName - (optional) the application to be used to open the
* file (for example, "chrome", "firefox")
* @param {function(Error)} callback - called with null on success, or
* an error object that contains a property 'code' with the exit
* code of the process.
*/
module.exports = open;
function open(target, appName, callback) {
var opener;
if (typeof(appName) === 'function') {
callback = appName;
appName = null;
}
switch (process.platform) {
case 'darwin':
if (appName) {
opener = 'open -a "' + escape(appName) + '"';
} else {
opener = 'open';
}
break;
case 'win32':
// if the first parameter to start is quoted, it uses that as the title
// so we pass a blank title so we can quote the file we are opening
if (appName) {
opener = 'start "" "' + escape(appName) + '"';
} else {
opener = 'start ""';
}
break;
default:
if (appName) {
opener = escape(appName);
} else {
// use Portlands xdg-open everywhere else
opener = path.join(__dirname, './xdg-open');
}
break;
}
if (process.env.SUDO_USER) {
opener = 'sudo -u ' + process.env.SUDO_USER + ' ' + opener;
}
return exec(opener + ' "' + escape(target) + '"', callback);
}
function escape(s) {
return s.replace(/"/g, '\\\"');
}

Some files were not shown because too many files have changed in this diff Show More