feat: 초기 프로젝트 설정 및 룰.md 파일 추가
This commit is contained in:
212
api.hyungi.net/node_modules/pm2/lib/API/Configuration.js
generated
vendored
Normal file
212
api.hyungi.net/node_modules/pm2/lib/API/Configuration.js
generated
vendored
Normal 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();
|
||||
});
|
||||
}
|
||||
335
api.hyungi.net/node_modules/pm2/lib/API/Containerizer.js
generated
vendored
Normal file
335
api.hyungi.net/node_modules/pm2/lib/API/Containerizer.js
generated
vendored
Normal 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
459
api.hyungi.net/node_modules/pm2/lib/API/Dashboard.js
generated
vendored
Normal 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
117
api.hyungi.net/node_modules/pm2/lib/API/Deploy.js
generated
vendored
Normal 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
775
api.hyungi.net/node_modules/pm2/lib/API/Extra.js
generated
vendored
Normal 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);
|
||||
});
|
||||
};
|
||||
};
|
||||
30
api.hyungi.net/node_modules/pm2/lib/API/ExtraMgmt/Docker.js
generated
vendored
Normal file
30
api.hyungi.net/node_modules/pm2/lib/API/ExtraMgmt/Docker.js
generated
vendored
Normal 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
315
api.hyungi.net/node_modules/pm2/lib/API/Log.js
generated
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
371
api.hyungi.net/node_modules/pm2/lib/API/LogManagement.js
generated
vendored
Normal file
371
api.hyungi.net/node_modules/pm2/lib/API/LogManagement.js
generated
vendored
Normal 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);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
};
|
||||
122
api.hyungi.net/node_modules/pm2/lib/API/Modules/LOCAL.js
generated
vendored
Normal file
122
api.hyungi.net/node_modules/pm2/lib/API/Modules/LOCAL.js
generated
vendored
Normal 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);
|
||||
});
|
||||
};
|
||||
148
api.hyungi.net/node_modules/pm2/lib/API/Modules/Modularizer.js
generated
vendored
Normal file
148
api.hyungi.net/node_modules/pm2/lib/API/Modules/Modularizer.js
generated
vendored
Normal 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
437
api.hyungi.net/node_modules/pm2/lib/API/Modules/NPM.js
generated
vendored
Normal 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
362
api.hyungi.net/node_modules/pm2/lib/API/Modules/TAR.js
generated
vendored
Normal 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
|
||||
}
|
||||
46
api.hyungi.net/node_modules/pm2/lib/API/Modules/flagExt.js
generated
vendored
Normal file
46
api.hyungi.net/node_modules/pm2/lib/API/Modules/flagExt.js
generated
vendored
Normal 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);
|
||||
}
|
||||
}
|
||||
120
api.hyungi.net/node_modules/pm2/lib/API/Modules/index.js
generated
vendored
Normal file
120
api.hyungi.net/node_modules/pm2/lib/API/Modules/index.js
generated
vendored
Normal 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
247
api.hyungi.net/node_modules/pm2/lib/API/Monit.js
generated
vendored
Normal 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
342
api.hyungi.net/node_modules/pm2/lib/API/Serve.js
generated
vendored
Normal 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
616
api.hyungi.net/node_modules/pm2/lib/API/Startup.js
generated
vendored
Normal 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
213
api.hyungi.net/node_modules/pm2/lib/API/UX/helpers.js
generated
vendored
Normal 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
9
api.hyungi.net/node_modules/pm2/lib/API/UX/index.js
generated
vendored
Normal 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
|
||||
193
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-describe.js
generated
vendored
Normal file
193
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-describe.js
generated
vendored
Normal 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)
|
||||
}
|
||||
31
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-ls-minimal.js
generated
vendored
Normal file
31
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-ls-minimal.js
generated
vendored
Normal 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
482
api.hyungi.net/node_modules/pm2/lib/API/UX/pm2-ls.js
generated
vendored
Normal 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
382
api.hyungi.net/node_modules/pm2/lib/API/Version.js
generated
vendored
Normal 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);
|
||||
};
|
||||
|
||||
}
|
||||
12
api.hyungi.net/node_modules/pm2/lib/API/interpreter.json
generated
vendored
Normal file
12
api.hyungi.net/node_modules/pm2/lib/API/interpreter.json
generated
vendored
Normal 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"
|
||||
}
|
||||
372
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/PM2IO.js
generated
vendored
Normal file
372
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/PM2IO.js
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
288
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/CliAuth.js
generated
vendored
Normal file
288
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/CliAuth.js
generated
vendored
Normal 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)
|
||||
})
|
||||
}
|
||||
}
|
||||
187
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/WebAuth.js
generated
vendored
Normal file
187
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/auth-strategies/WebAuth.js
generated
vendored
Normal 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)
|
||||
}
|
||||
}
|
||||
97
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/helpers.js
generated
vendored
Normal file
97
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/helpers.js
generated
vendored
Normal 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()
|
||||
// })
|
||||
// });
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
126
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/link.js
generated
vendored
Normal file
126
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/link.js
generated
vendored
Normal 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);
|
||||
};
|
||||
};
|
||||
16
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/motd
generated
vendored
Normal file
16
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/motd
generated
vendored
Normal 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
|
||||
26
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/motd.update
generated
vendored
Normal file
26
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/motd.update
generated
vendored
Normal 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
|
||||
|
||||
-------------
|
||||
28
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/welcome
generated
vendored
Normal file
28
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/pres/welcome
generated
vendored
Normal 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
|
||||
|
||||
-------------
|
||||
52
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/process-selector.js
generated
vendored
Normal file
52
api.hyungi.net/node_modules/pm2/lib/API/pm2-plus/process-selector.js
generated
vendored
Normal 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
375
api.hyungi.net/node_modules/pm2/lib/API/schema.json
generated
vendored
Normal 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|M|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|m|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|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"
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user