diff --git a/lib/blessed-widget/layout.js b/lib/blessed-widget/layout.js index 50c1402..b62bc07 100644 --- a/lib/blessed-widget/layout.js +++ b/lib/blessed-widget/layout.js @@ -1,255 +1,243 @@ -var blessed = require('blessed'), - chalk = require('chalk'), - async = require('async'), - widgets = require('./widgets'), - conf = require('../util/conf'), - _ = require('lodash'), - stats = require('../stat'), - Log = require('../util/log'); +var blessed = require('blessed') +var chalk = require('chalk') +var async = require('async') +var _ = require('lodash') +var widgets = require('./widgets') +var conf = require('../util/conf') +var Log = require('../util/log') -module.exports = Layout; +module.exports = Layout -var exiting = false; +var exiting = false /** * Create layout. * @param {Object} options */ -function Layout(options) { +function Layout (options) { if (!(this instanceof Layout)) { - return new Layout(options); + return new Layout(options) } - options = _.clone(options || {}); + options = _.clone(options || {}) if (!options.hostname) { - options.hostname = '127.0.0.1'; + options.hostname = '127.0.0.1' } if (!options.port) { - throw new Error('Port of socket.io server is required!'); + throw new Error('Port of socket.io server is required!') } - options.sockets = options.sockets || {}; - this.options = options; - this._eles = {}; - this._procCount = 0; -}; + options.sockets = options.sockets || {} + this.options = options + this._eles = {} + this._procCount = 0 +} /** * Render GUI. */ Layout.prototype.render = function (monitor) { - var self = this, - options = this.options, - jobs = {}; + var self = this + var options = this.options // Preparing all socket.io clients. - Object.keys(conf.NSP).forEach(function (ns) { - var nsl = ns.toLowerCase(); - if (options.sockets[nsl]) { - return; - } - jobs[nsl] = function (next) { - var opts = _.extend({ + async.series(Object.keys(conf.NSP).map(function (ns) { + return function (callback) { + var callbackOnce = _.once(callback) + var nsl = ns.toLowerCase() + if (options.sockets[nsl]) { + return callbackOnce() + } + + monitor.connect(_.extend({ namespace: conf.NSP[ns] - }, options); - - monitor.connect(opts, function (socket) { - console.info('Connected to', socket.nsp); - !next._called && next(null, socket); - next._called = true; + }, options), function (socket) { + console.info('Connected to', socket.nsp) + callbackOnce(null, socket) }, function (err, socket) { - console.log(err); - if (!next._called) { - next(err, socket); - next._called = true; - } else { - //Log(options.log); + if (err) { + return callbackOnce(new Error('Failed to connect to [' + ns + '] due to ' + err.message)) } - console.error('Failed due to', err.message, 'when connecting to', socket.nsp); - if (next._called) { - process.exit(0); - } - }); + }) } - }); - - var done = function (err, res) { + }), function (err, res) { if (err) { - return process.exit(0); + console.error(err.message) + return process.exit(0) } Log({ level: 1000 - }); - self.sockets = _.extend(res, options.sockets); - delete options.sockets; + }) + var connectedSockets = {} + res.forEach(function (socket) { + connectedSockets[socket.nsp] = socket + }) + self.sockets = _.extend(connectedSockets, options.sockets) + delete options.sockets - self._observe(); - self._draw(); + self._observe() + self._draw() setInterval(function () { - self._bindProcesses(); - }, 1000); - }; - if (_.keys(jobs).length == 0) { - return done(); - } - async.parallel(jobs, done); -}; + self._bindProcesses() + }, 1000) + }) +} /** * Observe socket.io events. */ Layout.prototype._observe = function () { - var self = this; - console.info('Listening socket events...'); - var socketSys = this._socket(conf.NSP.SYS); + var self = this + console.info('Listening socket events...') + var socketSys = this._socket(conf.NSP.SYS) socketSys.on('procs', function (procs) { self._procs = { data: procs, tick: Date.now() - }; - (typeof self._procs == 'undefined') && self._bindProcesses(); - }); - socketSys.emit('procs'); + } + if (typeof self._procs === 'undefined') { + self._bindProcesses() + } + }) + socketSys.emit('procs') this._socket(conf.NSP.PROC).on('proc', function (proc) { - if (!self._usages || proc.pid != self._usages.pid || self._usages.time == proc.time) { - return; + if (!self._usages || proc.pid !== self._usages.pid || self._usages.time === proc.time) { + return } - self._usages.time = proc.time; - self._usages.cpu.shift(); - self._usages.cpu.push(Math.min(100, Math.max(proc.usage.cpu, 1))); - self._usages.mem.shift(); - self._usages.mem.push(Math.min(100, Math.max(proc.usage.memory, 1))); - }); + self._usages.time = proc.time + self._usages.cpu.shift() + self._usages.cpu.push(Math.min(100, Math.max(proc.usage.cpu, 1))) + self._usages.mem.shift() + self._usages.mem.push(Math.min(100, Math.max(proc.usage.memory, 1))) + }) this._socket(conf.NSP.LOG).on('log', function (log) { - if (!self._eles.logs || self._lastLogPMId != log.pm_id) { - return; + if (!self._eles.logs || self._lastLogPMId !== log.pm_id) { + return } - self._eles.logs.log(log.msg); - }); -}; + self._eles.logs.log(log.msg) + }) +} /** * Bind processes to table. */ Layout.prototype._bindProcesses = function () { if (exiting || !this._eles.processes || !this._procs) { - return; + return } - if (this._procs.tick == this._procsLastTick) { + if (this._procs.tick === this._procsLastTick) { // Update tick only. - return setRows.call(this, true); + return setRows.call(this, true) } - if (typeof this._procsLastTick == 'undefined') { - this._describeInfo(0); - this._eles.processes.rows.on('select', onSelect.bind(this)); + if (typeof this._procsLastTick === 'undefined') { + this._describeInfo(0) + this._eles.processes.rows.on('select', onSelect.bind(this)) } - this._procsLastTick = this._procs.tick; + this._procsLastTick = this._procs.tick - setRows.call(this, true); + setRows.call(this, true) - function setRows(forceRefresh) { - var rows = [], - selectedIndex = this._eles.processes.rows.selected, - len = this._procs.data.length; + function setRows (forceRefresh) { + var rows = [] + var selectedIndex = this._eles.processes.rows.selected + var len = this._procs.data.length this._procs.data.forEach(function (p, i) { - var pm2 = p.pm2_env, - index = '[' + i + '/' + len + ']'; + var pm2 = p.pm2_env + var index = '[' + i + '/' + len + ']' rows.push([ ' ' + chalk.grey((index + Array(8 - index.length).join(' '))) + ' ' + p.name, pm2.restart_time, - pm2.status != 'online' ? '0s' : _fromNow(Math.ceil((Date.now() - pm2.pm_uptime) / 1000), true), - pm2.status == 'online' ? chalk.green('✔') : chalk.red('✘') - ]); - }); + pm2.status !== 'online' ? '0s' : _fromNow(Math.ceil((Date.now() - pm2.pm_uptime) / 1000), true), + pm2.status === 'online' ? chalk.green('✔') : chalk.red('✘') + ]) + }) this._eles.processes.setData({ headers: [' Name', 'Restarts', 'Uptime', ''], rows: rows - }); + }) - selectedIndex = typeof selectedIndex != 'undefined' ? selectedIndex : 0; - var maxIndex = this._eles.processes.rows.items.length - 1; + selectedIndex = typeof selectedIndex !== 'undefined' ? selectedIndex : 0 + var maxIndex = this._eles.processes.rows.items.length - 1 if (selectedIndex > maxIndex) { - selectedIndex = maxIndex; + selectedIndex = maxIndex } - this._eles.processes.rows.select(selectedIndex); + this._eles.processes.rows.select(selectedIndex) if (forceRefresh) { - onSelect.call(this); + onSelect.call(this) } } - function onSelect(item, selectedIndex) { - if (!!item) { - var lastIndex = this._lastSelectedIndex; + function onSelect (item, selectedIndex) { + if (!!item) { // eslint-disable-line no-extra-boolean-cast + var lastIndex = this._lastSelectedIndex - this._lastSelectedIndex = selectedIndex; - if (selectedIndex != lastIndex) { - this._describeInfo(selectedIndex); + this._lastSelectedIndex = selectedIndex + if (selectedIndex !== lastIndex) { + this._describeInfo(selectedIndex) } } - this._cpuAndMemUsage(this._lastSelectedIndex || 0); - this._displayLogs(this._lastSelectedIndex || 0); - this.screen.render(); + this._cpuAndMemUsage(this._lastSelectedIndex || 0) + this._displayLogs(this._lastSelectedIndex || 0) + this.screen.render() } -}; +} /** * Get description of a specified process. * @param {Number} index the selected row index. - * */ Layout.prototype._describeInfo = function (index) { - var pm2 = this._dataOf(index); + var pm2 = this._dataOf(index) if (!pm2) { return this._eles.json.setContent(_formatJSON({ message: 'There is no process running!' - })); + })) } if (pm2.pm2_env && pm2.pm2_env.env) { // Remove useless large-bytes attributes. - delete pm2.pm2_env.env['LS_COLORS']; + delete pm2.pm2_env.env['LS_COLORS'] } - delete pm2.monit; - this._eles.json.setContent(_formatJSON(pm2)); -}; + delete pm2.monit + this._eles.json.setContent(_formatJSON(pm2)) +} /** * CPU and Memory usage of a specific process * @param {Number} index the selected row index. - * */ Layout.prototype._cpuAndMemUsage = function (index) { - var pm2 = this._dataOf(index); + var pm2 = this._dataOf(index) if (!pm2) { - return; + return } if (!this._usages) { this._usages = { mem: [], cpu: [] - }; - var len = this._eles.cpu.width - 4; + } + var len = this._eles.cpu.width - 4 for (var i = 0; i < len; i++) { - this._usages.cpu.push(1); - this._usages.mem.push(1); + this._usages.cpu.push(1) + this._usages.mem.push(1) } } - if (pm2.pid != 0 && this._procCount == 2) { - this._procCount = -1; - this._socket(conf.NSP.PROC).emit('proc', pm2.pid); + if (pm2.pid !== 0 && this._procCount === 2) { + this._procCount = -1 + this._socket(conf.NSP.PROC).emit('proc', pm2.pid) } - this._procCount++; - this._usages.pid = pm2.pid; + this._procCount++ + this._usages.pid = pm2.pid - this._eles.cpu.setData(this._usages.cpu, 0, 100); - this._eles.cpu.setLabel('CPU Usage (' + (this._usages.cpu[this._usages.cpu.length - 1]).toFixed(2) + '%)'); + this._eles.cpu.setData(this._usages.cpu, 0, 100) + this._eles.cpu.setLabel('CPU Usage (' + (this._usages.cpu[this._usages.cpu.length - 1]).toFixed(2) + '%)') - this._eles.mem.setData(this._usages.mem, 0, 100); - this._eles.mem.setLabel('Memory Usage (' + (this._usages.mem[this._usages.mem.length - 1]).toFixed(2) + '%)'); -}; + this._eles.mem.setData(this._usages.mem, 0, 100) + this._eles.mem.setLabel('Memory Usage (' + (this._usages.mem[this._usages.mem.length - 1]).toFixed(2) + '%)') +} /** * Display logs. @@ -257,24 +245,24 @@ Layout.prototype._cpuAndMemUsage = function (index) { * @return {[type]} [description] */ Layout.prototype._displayLogs = function (index) { - var pm2 = this._dataOf(index); - if (!pm2 || this._lastLogPMId == pm2.pm_id) { - return; + var pm2 = this._dataOf(index) + if (!pm2 || this._lastLogPMId === pm2.pm_id) { + return } - this._killLogs(); - this._socket(conf.NSP.LOG).emit('tail', this._lastLogPMId = pm2.pm_id, true); -}; + this._killLogs() + this._socket(conf.NSP.LOG).emit('tail', this._lastLogPMId = pm2.pm_id, true) +} /** * Kill `tail` process * @return {[type]} [description] */ Layout.prototype._killLogs = function () { - if (typeof this._lastLogPMId == 'undefined') { - return; + if (typeof this._lastLogPMId === 'undefined') { + return } - this._socket(conf.NSP.LOG).emit('tail_kill', this._lastLogPMId); -}; + this._socket(conf.NSP.LOG).emit('tail_kill', this._lastLogPMId) +} /** * Get data by index. @@ -283,74 +271,74 @@ Layout.prototype._killLogs = function () { */ Layout.prototype._dataOf = function (index) { if (!this._procs || !Array.isArray(this._procs.data) || index >= this._procs.data.length) { - return null; + return null } - return this._procs.data[index]; -}; + return this._procs.data[index] +} /** * Draw elements. */ Layout.prototype._draw = function () { - console.info('Rendering dashboard...'); - var self = this; - var screen = blessed.Screen(); - screen.title = 'PM2 Monitor'; + console.info('Rendering dashboard...') + var self = this + var screen = blessed.Screen() + screen.title = 'PM2 Monitor' - var grid = _grid(screen); + var grid = _grid(screen) // Processes. - this._eles.processes = grid.get(0, 0); - this._bindProcesses(); + this._eles.processes = grid.get(0, 0) + this._bindProcesses() - this._eles.cpu = grid.get(1, 0); - this._eles.mem = grid.get(1, 1); + this._eles.cpu = grid.get(1, 0) + this._eles.mem = grid.get(1, 1) // Logs. - this._eles.logs = grid.get(2, 0); + this._eles.logs = grid.get(2, 0) // Detail. - this._eles.json = grid.get(0, 2); - var offset = Math.round(this._eles.json.height * 100 / this._eles.json.getScrollHeight()), - dir; + this._eles.json = grid.get(0, 2) + var offset = Math.round(this._eles.json.height * 100 / this._eles.json.getScrollHeight()) + var dir // Key bindings screen.key('s', function (ch, key) { if (exiting) { - return; + return } - var perc = Math.min((dir != 'down' ? offset : 0) + self._eles.json.getScrollPerc() + 5, 100); - dir = 'down'; + var perc = Math.min((dir !== 'down' ? offset : 0) + self._eles.json.getScrollPerc() + 5, 100) + dir = 'down' self._eles.json.setScrollPerc(perc) - }); + }) screen.key('w', function (ch, key) { if (exiting) { - return; + return } - var perc = Math.max(self._eles.json.getScrollPerc() - 5 - (dir != 'up' ? offset : 0), 0); - dir = 'up'; + var perc = Math.max(self._eles.json.getScrollPerc() - 5 - (dir !== 'up' ? offset : 0), 0) + dir = 'up' self._eles.json.setScrollPerc(perc) - }); + }) screen.key(['escape', 'q', 'C-c'], function (ch, key) { if (exiting) { - return; + return } - exiting = true; - this._killLogs(); - screen.title = 'PM2 Monitor (Exiting...)'; - screen.destroy(); - screen.title = ''; + exiting = true + this._killLogs() + screen.title = 'PM2 Monitor (Exiting...)' + screen.destroy() + screen.title = '' screen.cursorReset() setTimeout(function () { // clear screen. - // process.stdout.write('\u001B[2J\u001B[0;0f'); - process.exit(0); + // process.stdout.write('\u001B[2J\u001B[0;0f') + process.exit(0) }, 1000) - }.bind(this)); + }.bind(this)) - screen.render(); - this.screen = screen; -}; + screen.render() + this.screen = screen +} /** * Get socket.io object by namespace @@ -358,10 +346,10 @@ Layout.prototype._draw = function () { */ Layout.prototype._socket = function (ns) { if (ns && this.sockets) { - return this.sockets[_.trimLeft(ns, '/').toLowerCase()]; + return this.sockets[_.trimLeft(ns, '/').toLowerCase()] } - return null; -}; + return null +} /** * Grid of screen elements. @@ -369,7 +357,7 @@ Layout.prototype._socket = function (ns) { * @returns {*} * @private */ -function _grid(screen) { +function _grid (screen) { var style = { fg: '#013409', label: { @@ -379,7 +367,7 @@ function _grid(screen) { border: { fg: '#5e9166' } - }; + } // Layout. var grid = widgets.Grid({ rows: 3, @@ -387,7 +375,7 @@ function _grid(screen) { margin: 0, widths: [25, 25, 50], heights: [35, 10, 55] - }); + }) // Table of processes grid.set({ row: 0, @@ -403,7 +391,7 @@ function _grid(screen) { label: 'Processes (↑/↓ to move up/down, enter to select)', widths: [35, 15, 20, 15] } - }); + }) // Sparkline of CPU grid.set({ row: 1, @@ -425,7 +413,7 @@ function _grid(screen) { }, label: 'CPU Usage(%)' } - }); + }) // Sparkline of Memory grid.set({ @@ -448,7 +436,7 @@ function _grid(screen) { }, label: 'Memory Usage(%)' } - }); + }) // Logs grid.set({ @@ -463,7 +451,7 @@ function _grid(screen) { style: style, label: 'Logs' } - }); + }) // JSON data. grid.set({ @@ -479,10 +467,10 @@ function _grid(screen) { style: style, keys: true } - }); - grid.draw(screen); + }) + grid.draw(screen) - return grid; + return grid } /** @@ -491,20 +479,20 @@ function _grid(screen) { * @returns {XML|*|string|void} * @private */ -function _formatJSON(data) { - data = JSON.stringify(typeof data != 'string' ? data : JSON.parse(data), null, 2); +function _formatJSON (data) { + data = JSON.stringify(typeof data !== 'string' ? data : JSON.parse(data), null, 2) return data.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function (m) { - var color = 'blue'; + var color = 'blue' if (/^"/.test(m)) { - color = ['magenta', 'green'][/:$/.test(m) ? 0 : 1]; + color = ['magenta', 'green'][/:$/.test(m) ? 0 : 1] } else if (/true|false/.test(m)) { - color = 'blue'; + color = 'blue' } else if (/null|undefined/.test(m)) { - color = 'blue'; + color = 'blue' } - return chalk[color](m); - }); + return chalk[color](m) + }) } /** @@ -513,40 +501,18 @@ function _formatJSON(data) { * @param {Boolean} tiny show all of it. * @returns {string} */ -function _fromNow(tick, tiny) { +function _fromNow (tick, tiny) { if (tick < 60) { - return tick + 's'; + return tick + 's' } - var s = tick % 60 + 's'; + var s = tick % 60 + 's' if (tick < 3600) { - return parseInt(tick / 60) + 'm ' + s; + return parseInt(tick / 60) + 'm ' + s } - var m = parseInt((tick % 3600) / 60) + 'm '; + var m = parseInt((tick % 3600) / 60) + 'm ' if (tick < 86400) { - return parseInt(tick / 3600) + 'h ' + m + (!tiny ? '' : s); + return parseInt(tick / 3600) + 'h ' + m + (!tiny ? '' : s) } - var h = parseInt((tick % 86400) / 3600) + 'h '; - return parseInt(tick / 86400) + 'd ' + h + (!tiny ? '' : m + s); -} - -/** - * Wrap memory. - * @param {Float} mem - * @returns {string} - */ -function _getMem(mem) { - if (typeof mem == 'string') { - return mem; - } - - if (mem < 1024) { - return mem + 'B'; - } - if (mem < 1048576) { - return Math.round(mem / 1024) + 'K'; - } - if (mem < 1073741824) { - return Math.round(mem / 1048576) + 'M'; - } - return Math.round(mem / 1073741824) + 'G'; + var h = parseInt((tick % 86400) / 3600) + 'h ' + return parseInt(tick / 86400) + 'd ' + h + (!tiny ? '' : m + s) } diff --git a/lib/blessed-widget/widgets.js b/lib/blessed-widget/widgets.js index 2797cdb..23f3935 100644 --- a/lib/blessed-widget/widgets.js +++ b/lib/blessed-widget/widgets.js @@ -1,42 +1,39 @@ // Inspired by the blessed-contrib, but more powerful and free. // (c) Tjatse -var blessed = require('blessed'), - util = require('util'), - re_stripANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/g; +var blessed = require('blessed') +var util = require('util') +var re_stripANSI = /(?:(?:\u001b\[)|\u009b)(?:(?:[0-9]{1,3})?(?:(?:;[0-9]{0,3})*)?[A-M|f-m])|\u001b[A-M]/g -exports.Grid = Grid; -exports.Table = Table; -exports.Sparkline = Sparkline; -exports.Log = Log; +exports.Grid = Grid +exports.Table = Table +exports.Sparkline = Sparkline +exports.Log = Log -/*************************** - Grid - ***************************/ /** * Grid cells. * @param {Object} options * @returns {Grid} * @constructor */ -function Grid(options){ +function Grid (options) { if (!(this instanceof Grid)) { - return new Grid(options); + return new Grid(options) } options = util._extend({ margin: 2 - }, options || {}); + }, options || {}) - this.grids = []; + this.grids = [] for (var r = 0; r < options.rows; r++) { - this.grids[r] = []; + this.grids[r] = [] for (var c = 0; c < options.cols; c++) { - this.grids[r][c] = {}; + this.grids[r][c] = {} } } - this.options = options; + this.options = options } /** * Get instance in the specific row and column. @@ -44,99 +41,84 @@ function Grid(options){ * @param {Number} col * @returns {*} */ -Grid.prototype.get = function(row, col){ - return this.grids[row][col].instance; -}; +Grid.prototype.get = function (row, col) { + return this.grids[row][col].instance +} /** * Set element in the cell. * @param ele */ -Grid.prototype.set = function(ele){ +Grid.prototype.set = function (ele) { if (Array.isArray(ele)) { for (var i = 0; i < ele.length; i++) { - this.set(ele[i]); + this.set(ele[i]) } - return; + return } - this.grids[ele.row][ele.col] = util._extend({rowSpan: 1, colSpan: 1}, ele); -}; + this.grids[ele.row][ele.col] = util._extend({rowSpan: 1, colSpan: 1}, ele) +} /** * Draw grid. * @param {blessed.screen} screen */ -Grid.prototype.draw = function(screen, rect){ - var margin = this.options.margin, - rect = rect || { - width : 100, - height: 100, - top : 0, - left : 0 - }, - widths = this.options.widths || [], - heights = this.options.heights || [], - cols = this.options.cols, - rows = this.options.rows; +Grid.prototype.draw = function (screen, rect) { + rect = rect || { + width: 100, + height: 100, + top: 0, + left: 0 + } + var margin = this.options.margin + var widths = this.options.widths || [] + var heights = this.options.heights || [] + var cols = this.options.cols + var rows = this.options.rows - if (widths.length != cols) { - var avg = (rect.width - margin) / cols; + if (widths.length !== cols) { + var avg = (rect.width - margin) / cols for (var c = 0; c < cols; c++) { - widths.push(avg); + widths.push(avg) } } - if (heights.length != rows) { - var avg = (rect.height - margin) / rows; + if (heights.length !== rows) { + var avg = (rect.height - margin) / rows // eslint-disable-line no-redeclare for (var r = 0; r < rows; r++) { - heights.push(avg); + heights.push(avg) } } - for (var r = 0; r < rows; r++) { - for (var c = 0; c < cols; c++) { - var ele = this.grids[r][c]; + for (var r = 0; r < rows; r++) { // eslint-disable-line no-redeclare + for (var c = 0; c < cols; c++) { // eslint-disable-line no-redeclare + var ele = this.grids[r][c] if (!ele.element) { - continue; + continue } - var factorWidth = (rect.width - margin) / 100, - factorHeight = (rect.height - margin) / 100, - width = widths.slice(c, c + ele.colSpan).reduce(function(x, y){ - return x + y - }) * factorWidth, - height = heights.slice(r, r + ele.rowSpan).reduce(function(x, y){ - return x + y - }) * factorHeight, - top = rect.top + margin / 2 + (r == 0 ? 0 : heights.slice(0, r).reduce(function(x, y){ - return x + y - })) * factorHeight, - left = rect.left + margin / 2 + (c == 0 ? 0 : widths.slice(0, c).reduce(function(x, y){ - return x + y - })) * factorWidth; + var factorWidth = (rect.width - margin) / 100 + var factorHeight = (rect.height - margin) / 100 + var width = widths.slice(c, c + ele.colSpan).reduce(_reduce) * factorWidth + var height = heights.slice(r, r + ele.rowSpan).reduce(_reduce) * factorHeight + var top = rect.top + margin / 2 + (r === 0 ? 0 : heights.slice(0, r).reduce(_reduce)) * factorHeight + var left = rect.left + margin / 2 + (c === 0 ? 0 : widths.slice(0, c).reduce(_reduce)) * factorWidth if (ele.element instanceof Grid) { ele.element.draw(screen, { - width : width, + width: width, height: height, - top : top, - left : left - }); + top: top, + left: left + }) } else { screen.append(ele.instance = ele.element(util._extend(ele.options || {}, { - top : top + '%', - left : left + '%', - width : width + '%', + top: top + '%', + left: left + '%', + width: width + '%', height: height + '%' - }))); + }))) } } } -}; -/*************************** - End Of Grid - ***************************/ - -/*************************** - Table - ***************************/ +} /** * Table list. @@ -144,168 +126,156 @@ Grid.prototype.draw = function(screen, rect){ * @returns {Table} * @constructor */ -function Table(options){ +function Table (options) { if (!(this instanceof Table)) { - return new Table(options); + return new Table(options) } - this.options = options || {}; - this.options.tags = true; + this.options = options || {} + this.options.tags = true - blessed.Box.call(this, this.options); + blessed.Box.call(this, this.options) this.rows = blessed.list(util._extend(this.options.rows || {}, { - height : 0, - top : 1, - width : 0, - left : 0, + height: 0, + top: 1, + width: 0, + left: 0, selectedFg: '#fcfbac', selectedBg: '#398cc6', - fg : "#333", - keys : true - })); - this.append(this.rows); + fg: '#333', + keys: true + })) + this.append(this.rows) } -util.inherits(Table, blessed.Box); +util.inherits(Table, blessed.Box) /** * Inherits from blessed.Box */ -Table.prototype.render = function(){ - this.rows.focus(); - this.rows.width = this.width - 2; - this.rows.height = this.height - 4; - blessed.Box.prototype.render.call(this, this.options); -}; +Table.prototype.render = function () { + this.rows.focus() + this.rows.width = this.width - 2 + this.rows.height = this.height - 4 + blessed.Box.prototype.render.call(this, this.options) +} /** * Bind data to Table. * @param {Object} data */ -Table.prototype.setData = function(data){ - var widths = this.options.widths, def = true; +Table.prototype.setData = function (data) { + var widths = this.options.widths + var def = true if (!widths) { - widths = 24; - def = false; + widths = 24 + def = false } - var dataToString = function(d){ - return d.map(function(s, i){ - s = s.toString(); - var s1 = s.replace(re_stripANSI, ''); - var size = !def ? widths : widths[i], - len = size - s1.length; + var dataToString = function (d) { + return d.map(function (s, i) { + s = s.toString() + var s1 = s.replace(re_stripANSI, '') + var size = !def ? widths : widths[i] + var len = size - s1.length if (len < 0) { - s = s1.substr(0, size - 1) + '...'; + s = s1.substr(0, size - 1) + '...' } else { - s += Array(len).join(' '); + s += Array(len).join(' ') } - return s; - }).join(''); - }; + return s + }).join('') + } - var rows = []; + var rows = [] - data.rows.forEach(function(d){ + data.rows.forEach(function (d) { rows.push(dataToString(d)) - }); - this.setContent('{bold}' + dataToString(data.headers) + '{/bold}'); + }) + this.setContent('{bold}' + dataToString(data.headers) + '{/bold}') this.rows.setItems(rows) -}; -/*************************** - End Of TABLE - ***************************/ +} -/*************************** - Sparkline - ***************************/ /** * Sparkline. * @param {Object} options * @returns {Sparkline} * @constructor */ -function Sparkline(options){ +function Sparkline (options) { if (!(this instanceof Sparkline)) { - return new Sparkline(options); + return new Sparkline(options) } this.options = util._extend({ - chars : ['▂', '▃', '▄', '▅', '▆', '▇', '█'], - tags : true, + chars: ['▂', '▃', '▄', '▅', '▆', '▇', '█'], + tags: true, padding: { left: 1, - top : 1 + top: 1 } - }, options || {}); - blessed.Box.call(this, this.options); + }, options || {}) + blessed.Box.call(this, this.options) } -util.inherits(Sparkline, blessed.Box); +util.inherits(Sparkline, blessed.Box) /** * Set data. * @param {Array} data */ -Sparkline.prototype.setData = function(data, min, max){ - var chars = this.options.chars, - max = typeof max == 'undefined' ? Math.max.apply(null, data) : max, - min = typeof min == 'undefined' ? Math.min.apply(null, data) : min, - dis = max - min, - len = chars.length - 1; +Sparkline.prototype.setData = function (data, min, max) { + var chars = this.options.chars + max = typeof max === 'undefined' ? Math.max.apply(null, data) : max + min = typeof min === 'undefined' ? Math.min.apply(null, data) : min + var dis = max - min + var len = chars.length - 1 - if (dis == 0) { - dis = 1; + if (dis === 0) { + dis = 1 } - var content = data.map(function(n){ - var index = Math.round((n - min) / dis * len); - return chars[index]; - }).join(''); - this.setContent(content); -}; + var content = data.map(function (n) { + var index = Math.round((n - min) / dis * len) + return chars[index] + }).join('') + this.setContent(content) +} -/*************************** - END OF Sparkline - ***************************/ - -/*************************** - Log - ***************************/ /** * Log. * @param {Object} options * @returns {Log} * @constructor */ -function Log(options){ +function Log (options) { if (!(this instanceof Log)) { - return new Log(options); + return new Log(options) } - this.options = options || {}; + this.options = options || {} - blessed.ScrollableBox.call(this, this.options); + blessed.ScrollableBox.call(this, this.options) - this.logs = []; + this.logs = [] } -util.inherits(Log, blessed.ScrollableBox); +util.inherits(Log, blessed.ScrollableBox) /** * Log logs. * @param {String} str */ -Log.prototype.log = function(str, size){ - size = size || this.height; - this.logs.push(str); - var len = this.logs.length - size; +Log.prototype.log = function (str, size) { + size = size || this.height + this.logs.push(str) + var len = this.logs.length - size if (len > 0) { this.logs.splice(0, len) } - this.setContent(this.logs.join('\n')); - this.setScrollPerc(100); + this.setContent(this.logs.join('\n')) + this.setScrollPerc(100) } -/*************************** - END OF Log - ***************************/ \ No newline at end of file +function _reduce (x, y) { + return x + y +} diff --git a/lib/daemon.js b/lib/daemon.js index 067bb18..7a402a9 100644 --- a/lib/daemon.js +++ b/lib/daemon.js @@ -1,158 +1,159 @@ -var chalk = require('chalk'), - path = require('path'), - fs = require('fs'), - async = require('async'), - cp = require('child_process'), - fork = cp.fork, - spawn = cp.spawn, - Monitor = require('./monitor'), - Log = require('./util/log'); +var chalk = require('chalk') +var path = require('path') +var fs = require('fs') +var async = require('async') +var cp = require('child_process') +var fork = cp.fork +var spawn = cp.spawn +var Monitor = require('./monitor') +var Log = require('./util/log') -var processDirname = path.resolve(__dirname, '../'), - confFile = './pm2-gui.ini', - cmd = 'start'; +var processDirname = path.resolve(__dirname, '../') +var confFile = './pm2-gui.ini' +var cmd = 'start' if (process.argv.length > 2) { - cmd = process.argv[2]; + cmd = process.argv[2] } if (process.argv.length > 3) { - confFile = process.argv[3]; + confFile = process.argv[3] } -confFile = path.resolve(processDirname, confFile); +confFile = path.resolve(processDirname, confFile) if (!fs.existsSync(confFile)) { - console.error(chalk.bold(confFile), chalk.red('does not exist!')); - return process.exit(0); -} - -var monitor = Monitor({ + console.error(chalk.bold(confFile), chalk.red('does not exist!')) + process.exit(0) +} else { + var monitor = Monitor({ confFile: confFile - }), - daemonize = monitor.options.daemonize && cmd != 'mon'; + }) + var daemonize = monitor.options.daemonize && cmd !== 'mon' -Log(monitor.options.log); + Log(monitor.options.log) -var pidfile = path.resolve(processDirname, './pm2-gui.pid'); + var pidfile = path.resolve(processDirname, './pm2-gui.pid') -var Daemon = { - restarts: 0, - init: function(next) { - process.on('SIGTERM', Daemon.stop); - process.on('SIGINT', Daemon.stop); - process.on('SIGHUP', Daemon.restart); - next && next(); - }, - start: function(next) { - Daemon.worker = Daemon.fork(); - next && next(); - }, - restart: function() { - console.info('Restarting...'); - Daemon.kill(); - Daemon.start(); - }, - stop: function() { - console.info('Stopping...'); - Daemon.kill(); - daemonize && fs.existsSync(pidfile) && fs.unlinkSync(pidfile); - process.exit(0); - }, - kill: function() { - if (Daemon.timer) { - clearTimeout(Daemon.timer); - Daemon.timer = null; - } - if (Daemon.worker) { - Daemon.worker.suicide = true; - Daemon.worker.kill(); - } - }, - fork: function() { - console.info('Forking slave...'); - Daemon.timer = null; - var worker = fork(path.resolve(processDirname, 'pm2-gui.js'), [cmd, confFile, '--color'], { - silent: daemonize, - env: process.env - }); - worker.on('exit', function(code, signal) { - if (code != 0) { - if (Daemon.restarts < 10) { - Daemon.restarts++; - setTimeout(function() { - Daemon.restarts--; - }, 20000); - } else { - console.error(Daemon.restarts + ' restarts in 20 seconds, view the logs to investigate the crash problem.'); - return process.exit(0); - } + var Daemon = { + restarts: 0, + init: function (next) { + process.on('SIGTERM', Daemon.stop) + process.on('SIGINT', Daemon.stop) + process.on('SIGHUP', Daemon.restart) + next && next() + }, + start: function (next) { + Daemon.worker = Daemon.fork() + next && next() + }, + restart: function () { + console.info('Restarting...') + Daemon.kill() + Daemon.start() + }, + stop: function () { + console.info('Stopping...') + Daemon.kill() + daemonize && fs.existsSync(pidfile) && fs.unlinkSync(pidfile) + process.exit(0) + }, + kill: function () { + if (Daemon.timer) { + clearTimeout(Daemon.timer) + Daemon.timer = null } - if (!worker.suicide && code !== 0) { - Daemon.timer = setTimeout(Daemon.fork, 3000); + if (Daemon.worker) { + Daemon.worker.suicide = true + Daemon.worker.kill() } - }); - - worker.on('message', function(message) { - if (typeof message == 'object' && message.action) - if (message.action == 'restart') { - Daemon.restart(); + }, + fork: function () { + console.info('Forking slave...') + Daemon.timer = null + var worker = fork(path.resolve(processDirname, 'pm2-gui.js'), [cmd, confFile, '--color'], { + silent: daemonize, + env: process.env + }) + worker.on('exit', function (code, signal) { + if (code !== 0) { + if (Daemon.restarts < 10) { + Daemon.restarts++ + setTimeout(function () { + Daemon.restarts-- + }, 20000) + } else { + console.error(Daemon.restarts + ' restarts in 20 seconds, view the logs to investigate the crash problem.') + return process.exit(0) + } } - }); + if (!worker.suicide && code !== 0) { + Daemon.timer = setTimeout(Daemon.fork, 3000) + } + }) - var logDir = monitor.options.log.dir, - stdout = 'pm2-gui.out', - stderr = 'pm2-gui.err'; + worker.on('message', function (message) { + if (typeof message === 'object' && message.action) { + if (message.action === 'restart') { + Daemon.restart() + } + } + }) - if (!logDir) { - logDir = './logs'; - } - logDir = path.resolve(processDirname, logDir); - if (!fs.existsSync(logDir)) { - fs.mkdirSync(logDir); - } + var logDir = monitor.options.log.dir + var stdout = 'pm2-gui.out' + var stderr = 'pm2-gui.err' - if (daemonize) { - stdout = fs.createWriteStream(path.join(logDir, stdout)); - stderr = fs.createWriteStream(path.join(logDir, stderr)); - worker.stdout.pipe(stdout); - worker.stderr.pipe(stderr); + if (!logDir) { + logDir = './logs' + } + logDir = path.resolve(processDirname, logDir) + if (!fs.existsSync(logDir)) { + fs.mkdirSync(logDir) + } - fs.writeFile(pidfile, worker.pid); + if (daemonize) { + stdout = fs.createWriteStream(path.join(logDir, stdout)) + stderr = fs.createWriteStream(path.join(logDir, stderr)) + worker.stdout.pipe(stdout) + worker.stderr.pipe(stderr) + + fs.writeFile(pidfile, worker.pid) + } + return worker + }, + daemonize: function () { + if (process.env.daemonized) { + console.info('Daemonized with pid [' + process.pid + '].') + return + } + console.info('Spawning daemon...') + var args = [].concat(process.argv) + args.shift() + var env = process.env + env.daemonized = true + var child = spawn(process.execPath, args, { + env: env, + detached: false, + cwd: processDirname, + stdio: ['ignore', process.stdout, process.stderr] + }) + child.unref() + process.exit() } - return worker; - }, - daemonize: function() { - if (process.env.daemonized) { - console.info('Daemonized with pid [' + process.pid + '].'); - return; - } - console.info('Spawning daemon...'); - var args = [].concat(process.argv); - args.shift(); - var env = process.env; - env.daemonized = true; - var child = spawn(process.execPath, args, { - env: env, - detached: false, - cwd: processDirname, - stdio: ['ignore', process.stdout, process.stderr] - }); - child.unref(); - process.exit(); } -}; -if (daemonize) { - Daemon.daemonize(); + if (daemonize) { + Daemon.daemonize() + } + + process.title = 'pm2-gui daemon ' + confFile + async.series([ + Daemon.init, + Daemon.start + ], function (err) { + if (err) { + console.error(err.stack) + } + }) } - -process.title = 'pm2-gui daemon'; -async.series([ - Daemon.init, - Daemon.start -], function(err) { - if (err) { - console.error(err.stack); - } -}); \ No newline at end of file diff --git a/lib/monitor.js b/lib/monitor.js index a97dfae..4ade5b5 100644 --- a/lib/monitor.js +++ b/lib/monitor.js @@ -1,19 +1,19 @@ -var fs = require('fs'), - path = require('path'), - _ = require('lodash'), - chalk = require('chalk'), - ansiHTML = require('ansi-html'), - totalmem = require('os').totalmem(), - pidusage = require('pidusage'), - url = require('url'), - socketIOClient = require('socket.io-client'), - pm = require('./pm'), - stat = require('./stat'), - conf = require('./util/conf'), - Log = require('./util/log'), - defConf; +var fs = require('fs') +var path = require('path') +var _ = require('lodash') +var chalk = require('chalk') +var ansiHTML = require('ansi-html') +var totalmem = require('os').totalmem() +var pidusage = require('pidusage') +var url = require('url') +var socketIOClient = require('socket.io-client') +var pm = require('./pm') +var stat = require('./stat') +var conf = require('./util/conf') +var Log = require('./util/log') +var defConf -module.exports = Monitor; +module.exports = Monitor /** * Monitor of project monitor web. @@ -21,33 +21,33 @@ module.exports = Monitor; * @returns {Monitor} * @constructor */ -function Monitor(options) { +function Monitor (options) { if (!(this instanceof Monitor)) { - return new Monitor(options); + return new Monitor(options) } // Initialize... - this._init(options); -}; + this._init(options) +} -Monitor.ACCEPT_KEYS = ['pm2', 'refresh', 'daemonize', 'max_restarts', 'port', 'log', 'agent', 'remotes', 'origins']; -Monitor.DEF_CONF_FILE = 'pm2-gui.ini'; -Monitor.PM2_DAEMON_PROPS = ['DAEMON_RPC_PORT', 'DAEMON_PUB_PORT']; +Monitor.ACCEPT_KEYS = ['pm2', 'refresh', 'daemonize', 'max_restarts', 'port', 'log', 'agent', 'remotes', 'origins'] +Monitor.DEF_CONF_FILE = 'pm2-gui.ini' +Monitor.PM2_DAEMON_PROPS = ['DAEMON_RPC_PORT', 'DAEMON_PUB_PORT'] /** * Run socket.io server. */ Monitor.prototype.run = function () { - this._noClient = true; + this._noClient = true - this._tails = {}; - this._usages = {}; + this._tails = {} + this._usages = {} // Observe PM2 - this._observePM2(); + this._observePM2() - this._listeningSocketIO(); -}; + this._listeningSocketIO() +} /** * Quit monitor. @@ -55,48 +55,47 @@ Monitor.prototype.run = function () { */ Monitor.prototype.quit = function () { if (this.pm2Sock) { - console.debug('Closing pm2 pub emitter socket.'); - this.pm2Sock.close(); + console.debug('Closing pm2 pub emitter socket.') + this.pm2Sock.close() } if (this._sockio) { - console.debug('Closing socket.io server.'); - this._sockio.close(); + console.debug('Closing socket.io server.') + this._sockio.close() - console.debug('Destroying tails.'); - this._killTailProcess(); + console.debug('Destroying tails.') + this._killTailProcess() } -}; +} /** * Connect to socket.io server. * @param {String} ns the namespace. - * @param {Function} success - * @param {Function} failure + * @param {Function} success + * @param {Function} failure */ Monitor.prototype.connect = function (options, success, failure) { if (!options.port) { - throw new Error('Port is required!'); + throw new Error('Port is required!') } - var auth, - serverUri = Monitor.toConnectionString(options); + var serverUri = Monitor.toConnectionString(options) - console.info('Connecting to', serverUri); - var socket = socketIOClient(serverUri); + success = _.once(success) + failure = _.once(failure) + + console.info('Connecting to', serverUri) + var socket = socketIOClient(serverUri) socket.on('connect', function () { - !success._called && success(socket); - success._called = true; - }); + success(socket) + }) socket.on('error', function (err) { - !failure._called && failure(err, socket); - failure._called = true; - }); + !failure(err, socket) + }) socket.on('connect_error', function (err) { - !failure._called && failure(err, socket); - failure._called = true; - }); -}; + !failure(err, socket) + }) +} /** * Resolve home path. @@ -105,69 +104,69 @@ Monitor.prototype.connect = function (options, success, failure) { * @private */ Monitor.prototype._resolveHome = function (pm2Home) { - if (pm2Home && pm2Home.indexOf('~/') == 0) { + if (pm2Home && pm2Home.indexOf('~/') === 0) { // Get root directory of PM2. - pm2Home = process.env.PM2_HOME || path.resolve(process.env.HOME || process.env.HOMEPATH, pm2Home.substr(2)); + pm2Home = process.env.PM2_HOME || path.resolve(process.env.HOME || process.env.HOMEPATH, pm2Home.substr(2)) // Make sure exist. if (!pm2Home || !fs.existsSync(pm2Home)) { - throw new Error('PM2 root can not be located, try to initialize PM2 by executing `pm2 ls` or set environment variable vi `export PM2_HOME=[ROOT]`.'); + throw new Error('PM2 root can not be located, try to initialize PM2 by executing `pm2 ls` or set environment variable vi `export PM2_HOME=[ROOT]`.') } } - return pm2Home; -}; + return pm2Home +} /** * Initialize options and configurations. * @private */ Monitor.prototype._init = function (options) { - options = options || {}; + options = options || {} - defConf = conf.File(options.confFile || path.resolve(__dirname, '..', Monitor.DEF_CONF_FILE)).loadSync().valueOf(); - defConf = _.pick.call(null, defConf, Monitor.ACCEPT_KEYS); + defConf = conf.File(options.confFile || path.resolve(__dirname, '..', Monitor.DEF_CONF_FILE)).loadSync().valueOf() + defConf = _.pick.call(null, defConf, Monitor.ACCEPT_KEYS) - options = _.pick.apply(options, Monitor.ACCEPT_KEYS).valueOf(); - options = _.defaults(options, defConf); + options = _.pick.apply(options, Monitor.ACCEPT_KEYS).valueOf() + options = _.defaults(options, defConf) - options.pm2 = this._resolveHome(options.pm2); - Log(options.log); + options.pm2 = this._resolveHome(options.pm2) + Log(options.log) // Load PM2 config. - var pm2ConfPath = path.join(options.pm2, 'conf.js'), - fbMsg = ''; + var pm2ConfPath = path.join(options.pm2, 'conf.js') + var fbMsg = '' try { - options.pm2Conf = require(pm2ConfPath)(options.pm2); + options.pm2Conf = require(pm2ConfPath)(options.pm2) if (!options.pm2Conf) { - throw new Error(404); + throw new Error(404) } } catch (err) { - fbMsg = 'Can not load PM2 config, the file "' + pm2ConfPath + '" does not exist or empty, fallback to auto-load by pm2 home. '; - console.warn(fbMsg); + fbMsg = 'Can not load PM2 config, the file "' + pm2ConfPath + '" does not exist or empty, fallback to auto-load by pm2 home. ' + console.warn(fbMsg) options.pm2Conf = { DAEMON_RPC_PORT: path.resolve(options.pm2, 'rpc.sock'), DAEMON_PUB_PORT: path.resolve(options.pm2, 'pub.sock'), PM2_LOG_FILE_PATH: path.resolve(options.pm2, 'pm2.log') - }; + } } Monitor.PM2_DAEMON_PROPS.forEach(function (prop) { - var val = options.pm2Conf[prop]; + var val = options.pm2Conf[prop] if (!val || !fs.existsSync(val)) { - throw new Error(fbMsg + 'Unfortunately ' + (val || prop) + ' can not found, please makesure that your pm2 is running and the home path is correct.'); + throw new Error(fbMsg + 'Unfortunately ' + (val || prop) + ' can not found, please makesure that your pm2 is running and the home path is correct.') } - }); + }) // Bind socket.io server to context. if (options.sockio) { - this.sockio = options.sockio; - delete options.sockio; + this.sockio = options.sockio + delete options.sockio } // Bind to context. - this.options = options; - Object.freeze(this.options); -}; + this.options = options + Object.freeze(this.options) +} /** * Connection event of `sys` namespace. @@ -175,39 +174,41 @@ Monitor.prototype._init = function (options) { * @private */ Monitor.prototype._connectSysSock = function (socket) { - var self = this; + var self = this // Still has one client connects to server at least. - self._noClient = false; + self._noClient = false socket.on('disconnect', function () { // Check connecting client. - self._noClient = self._sockio.of(conf.NSP.SYS).sockets.length == 0; - }); + self._noClient = self._sockio.of(conf.NSP.SYS).sockets.length === 0 + }) // Trigger actions of process. socket.on('action', function (action, id) { - console.debug('[pm2:' + id + ']', action, 'sending to pm2 daemon...'); + console.debug('[pm2:' + id + ']', action, 'sending to pm2 daemon...') pm.action(self.options.pm2Conf.DAEMON_RPC_PORT, action, id, function (err, forceRefresh) { if (err) { - console.error(action, err.message); - return socket.emit('action', id, err.message); + console.error(action, err.message) + return socket.emit('action', id, err.message) } - console.debug('[pm2:' + id + ']', action, 'completed!'); - forceRefresh && self._throttleRefresh(); - }); - }); - sendProcs(); - socket.on('procs', sendProcs); - self._pm2Ver(socket); - this._sysStat && this._broadcast('system_stat', this._sysStat); + console.debug('[pm2:' + id + ']', action, 'completed!') + forceRefresh && self._throttleRefresh() + }) + }) + sendProcs() + socket.on('procs', sendProcs) + self._pm2Ver(socket) + this._sysStat && this._broadcast('system_stat', this._sysStat) // Grep system states once and again. - (this._status != 'R') && this._nextTick(this.options.refresh || 5000); - - function sendProcs() { - self._procs && socket.emit(typeof self._procs == 'string' ? 'info' : 'procs', self._procs); + if (this._status !== 'R') { + this._nextTick(this.options.refresh || 5000) } -}; + + function sendProcs () { + self._procs && socket.emit(typeof self._procs === 'string' ? 'info' : 'procs', self._procs) + } +} /** * Connection event of `log` namespace. @@ -215,22 +216,22 @@ Monitor.prototype._connectSysSock = function (socket) { * @private */ Monitor.prototype._connectLogSock = function (socket) { - var self = this; + var self = this // Emit error. - function emitError(err, pm_id, keepANSI) { + function emitError (err, pm_id, keepANSI) { var data = { pm_id: pm_id, msg: keepANSI ? chalk.red(err.message) : 'Error: ' + err.message + '' - }; - self._broadcast.call(self, 'log', data, conf.NSP.LOG); + } + self._broadcast.call(self, 'log', data, conf.NSP.LOG) // eslint-disable-line no-useless-call } - function startTailProcess(pm_id, keepANSI) { - socket._pm_id = pm_id; + function startTailProcess (pm_id, keepANSI) { + socket._pm_id = pm_id if (self._tails[pm_id]) { - return; + return } // Tail logs. @@ -240,39 +241,39 @@ Monitor.prototype._connectLogSock = function (socket) { pm_id: pm_id }, function (err, lines) { if (err) { - return emitError(err, pm_id, keepANSI); + return emitError(err, pm_id, keepANSI) } // Emit logs to clients. var data = { pm_id: pm_id, msg: lines.map(function (line) { if (!keepANSI) { - line = line.replace(/\s/, ' '); - return '' + ansiHTML(line) + ''; + line = line.replace(/\s/, ' ') + return '' + ansiHTML(line) + '' } else { - return line; + return line } }).join(keepANSI ? '\n' : '') - }; - self._broadcast.call(self, 'log', data, conf.NSP.LOG); + } + self._broadcast.call(self, 'log', data, conf.NSP.LOG) // eslint-disable-line no-useless-call }, function (err, tail) { if (err) { - return emitError(err, pm_id, keepANSI); + return emitError(err, pm_id, keepANSI) } if (!tail) { - return emitError(new Error('No log can be found.'), pm_id, keepANSI); + return emitError(new Error('No log can be found.'), pm_id, keepANSI) } - console.info('[pm2:' + pm_id + ']', 'tail starting...'); - self._tails[pm_id] = tail; - }); + console.info('[pm2:' + pm_id + ']', 'tail starting...') + self._tails[pm_id] = tail + }) } - socket.on('disconnect', self._killTailProcess.bind(self)); - socket.on('tail_kill', self._killTailProcess.bind(self)); - socket.on('tail', startTailProcess); - console.info('Connected to ' + socket.nsp.name + '!'); -}; + socket.on('disconnect', self._killTailProcess.bind(self)) + socket.on('tail_kill', self._killTailProcess.bind(self)) + socket.on('tail', startTailProcess) + console.info('Connected to ' + socket.nsp.name + '!') +} /** * Connection event of `proc` namespace. @@ -280,74 +281,74 @@ Monitor.prototype._connectLogSock = function (socket) { * @private */ Monitor.prototype._connectProcSock = function (socket) { - var self = this; + var self = this // Emit error. - function emitError(err, pid) { + function emitError (err, pid) { var data = { pid: pid, msg: 'Error: ' + err.message + '' - }; - self._broadcast.call(self, 'proc', data, conf.NSP.PROC); + } + self._broadcast.call(self, 'proc', data, conf.NSP.PROC) // eslint-disable-line no-useless-call } - function killObserver() { - var socks = self._sockio.of(conf.NSP.PROC).sockets, - canNotBeDeleted = {}; + function killObserver () { + var socks = self._sockio.of(conf.NSP.PROC).sockets + var canNotBeDeleted = {} if (Array.isArray(socks) && socks.length > 0) { socks.forEach(function (sock) { if (sock._pid) { - canNotBeDeleted[sock._pid.toString()] = 1; + canNotBeDeleted[sock._pid.toString()] = 1 } - }); + }) } for (var pid in self._usages) { - var timer; + var timer if (!canNotBeDeleted[pid] && (timer = self._usages[pid])) { - clearInterval(timer); - delete self._usages[pid]; - console.debug('[pid:' + pid + ']', 'cpu and memory observer destroyed!'); + clearInterval(timer) + delete self._usages[pid] + console.debug('[pid:' + pid + ']', 'cpu and memory observer destroyed!') } } } - function runObserver(pid) { - socket._pid = pid; + function runObserver (pid) { + socket._pid = pid - var pidStr = pid.toString(); + var pidStr = pid.toString() if (self._usages[pidStr]) { - return; + return } - console.debug('[pid:' + pidStr + ']', 'cpu and memory observer is running...'); + console.debug('[pid:' + pidStr + ']', 'cpu and memory observer is running...') - function runTimer() { + function runTimer () { pidusage.stat(pid, function (err, stat) { if (err) { - clearInterval(ctx._usages[pidStr]); - delete ctx._usages[pidStr]; - return emitError.call(self, err, pid); + clearInterval(self._usages[pidStr]) + delete self._usages[pidStr] + return emitError.call(self, err, pid) } - stat.memory = stat.memory * 100 / totalmem; + stat.memory = stat.memory * 100 / totalmem var data = { pid: pid, time: Date.now(), usage: stat - }; - self._broadcast.call(self, 'proc', data, conf.NSP.PROC); - }); + } + self._broadcast.call(self, 'proc', data, conf.NSP.PROC) // eslint-disable-line no-useless-call + }) } - self._usages[pidStr] = setInterval(runTimer, 3000); - runTimer(this); + self._usages[pidStr] = setInterval(runTimer, 3000) + runTimer(this) } - socket.on('disconnect', killObserver); - socket.on('proc', runObserver); - console.info('Connected to ' + socket.nsp.name + '!'); -}; + socket.on('disconnect', killObserver) + socket.on('proc', runObserver) + console.info('Connected to ' + socket.nsp.name + '!') +} /** * Grep system state loop @@ -356,23 +357,23 @@ Monitor.prototype._connectProcSock = function (socket) { */ Monitor.prototype._nextTick = function (tick, continuously) { // Return it if worker is running. - if (this._status == 'R' && !continuously) { - return; + if (this._status === 'R' && !continuously) { + return } // Running - this._status = 'R'; - console.debug('monitor heartbeat per', tick + 'ms'); + this._status = 'R' + console.debug('monitor heartbeat per', tick + 'ms') // Grep system state this._systemStat(function () { // If there still has any client, grep again after `tick` ms. if (!this._noClient) { - return setTimeout(this._nextTick.bind(this, tick, true), tick); + return setTimeout(this._nextTick.bind(this, tick, true), tick) } // Stop - delete this._status; - console.debug('monitor heartbeat destroyed!'); - }); -}; + delete this._status + console.debug('monitor heartbeat destroyed!') + }) +} /** * Grep system states. @@ -383,33 +384,33 @@ Monitor.prototype._systemStat = function (cb) { stat.cpuUsage(function (err, cpu_usage) { if (err) { // Log only. - console.error('Can not load system/cpu/memory information: ', err.message); + console.error('Can not load system/cpu/memory information: ', err.message) } else { // System states. this._sysStat = _.defaults(_(stat).pick('cpus', 'arch', 'hostname', 'platform', 'release', 'uptime', 'memory').clone(), { cpu: cpu_usage - }); - this._broadcast.call(this, 'system_stat', this._sysStat); + }) + this._broadcast.call(this, 'system_stat', this._sysStat) // eslint-disable-line no-useless-call } - cb.call(this); - }, this); -}; + cb.call(this) + }, this) +} /** * Observe PM2 * @private */ Monitor.prototype._observePM2 = function () { - var pm2Daemon = this.options.pm2Conf.DAEMON_PUB_PORT; - console.info('Connecting to pm2 daemon:', pm2Daemon); + var pm2Daemon = this.options.pm2Conf.DAEMON_PUB_PORT + console.info('Connecting to pm2 daemon:', pm2Daemon) this.pm2Sock = pm.sub(pm2Daemon, function (data) { - console.info(chalk.magenta(data.event), data.process.name + '-' + data.process.pm_id); - this._throttleRefresh(); - }, this); + console.info(chalk.magenta(data.event), data.process.name + '-' + data.process.pm_id) + this._throttleRefresh() + }, this) // Enforce a refresh operation if RPC is not online. - this._throttleRefresh(); -}; + this._throttleRefresh() +} /** * Throttle the refresh behavior to avoid refresh bomb @@ -417,13 +418,13 @@ Monitor.prototype._observePM2 = function () { */ Monitor.prototype._throttleRefresh = function () { if (this._throttle) { - clearTimeout(this._throttle); + clearTimeout(this._throttle) } this._throttle = setTimeout(function (ctx) { - ctx._throttle = null; - ctx._refreshProcs(); - }, 500, this); -}; + ctx._throttle = null + ctx._refreshProcs() + }, 500, this) +} /** * Refresh processes @@ -432,45 +433,45 @@ Monitor.prototype._throttleRefresh = function () { Monitor.prototype._refreshProcs = function () { pm.list(this.options.pm2Conf.DAEMON_RPC_PORT, function (err, procs) { if (err) { - return this._broadcast('info', 'Can not connect to pm2 daemon, ' + err.message); + return this._broadcast('info', 'Can not connect to pm2 daemon, ' + err.message) } // Wrap processes and cache them. this._procs = procs.map(function (proc) { proc.pm2_env = proc.pm2_env || { USER: 'UNKNOWN' - }; + } var pm2_env = { user: proc.pm2_env.USER - }; + } for (var key in proc.pm2_env) { // Ignore useless fields. - if (key.slice(0, 1) == '_' || - key.indexOf('axm_') == 0 || !!~['versioning', 'command'].indexOf(key) || + if (key.slice(0, 1) === '_' || + key.indexOf('axm_') === 0 || !!~['versioning', 'command'].indexOf(key) || key.charCodeAt(0) <= 90) { - continue; + continue } - pm2_env[key] = proc.pm2_env[key]; + pm2_env[key] = proc.pm2_env[key] } - proc.pm2_env = pm2_env; - return proc; - }); + proc.pm2_env = pm2_env + return proc + }) // Emit to client. - this._broadcast('procs', this._procs); + this._broadcast('procs', this._procs) }, this) -}; +} /** * Get PM2 version and return it to client. * @private */ Monitor.prototype._pm2Ver = function (socket) { - var pm2RPC = this.options.pm2Conf.DAEMON_RPC_PORT; - console.info('Fetching pm2 version:', pm2RPC); + var pm2RPC = this.options.pm2Conf.DAEMON_RPC_PORT + console.info('Fetching pm2 version:', pm2RPC) pm.version(pm2RPC, function (err, version) { - socket.emit('pm2_ver', (err || !version) ? '0.0.0' : version); - }); -}; + socket.emit('pm2_ver', (err || !version) ? '0.0.0' : version) + }) +} /** * Broadcast to all connected clients. @@ -480,14 +481,14 @@ Monitor.prototype._pm2Ver = function (socket) { * @private */ Monitor.prototype._broadcast = function (event, data, nsp) { - nsp = nsp || conf.NSP.SYS; + nsp = nsp || conf.NSP.SYS if (this._noClient) { return console.debug('No client is connecting, ignore broadcasting', event, 'to', nsp) } - console.debug('Broadcasting', event, 'to', nsp); - this._sockio.of(nsp).emit(event, data); -}; + console.debug('Broadcasting', event, 'to', nsp) + this._sockio.of(nsp).emit(event, data) +} /** * Destroy tails. @@ -495,65 +496,65 @@ Monitor.prototype._broadcast = function (event, data, nsp) { * @return {[type]} */ Monitor.prototype._killTailProcess = function (pm_id) { - var self = this; + var self = this - function killTail(id) { - var tail = self._tails[id]; + function killTail (id) { + var tail = self._tails[id] if (!tail) { - return; + return } try { - tail.kill('SIGTERM'); + tail.kill('SIGTERM') } catch (err) {} - delete self._tails[id]; - console.info('[pm2:' + id + ']', 'tail destroyed!'); + delete self._tails[id] + console.info('[pm2:' + id + ']', 'tail destroyed!') } if (!isNaN(pm_id)) { - return killTail(pm_id); + return killTail(pm_id) } - var socks = self._sockio.of(conf.NSP.LOG).sockets, - canNotBeDeleted = {}; + var socks = self._sockio.of(conf.NSP.LOG).sockets + var canNotBeDeleted = {} if (socks && socks.length > 0) { socks.forEach(function (sock) { - canNotBeDeleted[sock._pm_id] = 1; - }); + canNotBeDeleted[sock._pm_id] = 1 + }) } - for (var pm_id in self._tails) { - if (!canNotBeDeleted[pm_id]) { - killTail(pm_id); + for (var _id in self._tails) { + if (!canNotBeDeleted[_id]) { + killTail(_id) } } -}; +} /** * Listening all the nsp. */ Monitor.prototype._listeningSocketIO = function () { if (!this._sockio || this._sockio._listening) { - console.warn('Avoid duplicated listening!'); - return; + console.warn('Avoid duplicated listening!') + return } - this._sockio._listening = true; + this._sockio._listening = true for (var nsp in conf.NSP) { - this._sockio.of(conf.NSP[nsp]).on('connection', this['_connect' + (nsp[0] + nsp.toLowerCase().slice(1)) + 'Sock'].bind(this)); - console.info('Listening connection event on', nsp.toLowerCase()); + this._sockio.of(conf.NSP[nsp]).on('connection', this['_connect' + (nsp[0] + nsp.toLowerCase().slice(1)) + 'Sock'].bind(this)) + console.info('Listening connection event on', nsp.toLowerCase()) } - var auth; + var auth if (!(this.options.agent && (auth = this.options.agent.authorization))) { - return; + return } this._sockio.use(function (socket, next) { if (auth !== socket.handshake.query.auth) { - return next(new Error('unauthorized')); + return next(new Error('unauthorized')) } - next(); - }); -}; + next() + }) +} /** * List all available monitors. @@ -561,54 +562,54 @@ Monitor.prototype._listeningSocketIO = function () { * @return {Object} */ Monitor.available = function (options) { - options.agent = options.agent || {}; - var remotable = options.remotes && _.keys(options.remotes).length > 0; + options.agent = options.agent || {} + var remotable = options.remotes && _.keys(options.remotes).length > 0 if (options.agent.offline && !remotable) { - return null; + return null } - options.port = options.port || 8088; + options.port = options.port || 8088 var q = { - name: 'socket_server', - message: 'Which socket server would you wanna connect to', - type: 'list', - choices: [] - }, - wrapLocal = function () { - return { - value: (options.agent && options.agent.authorization ? options.agent.authorization + '@' : '') + '127.0.0.1:' + options.port, - short: 'localhost' - }; - }; - if (!remotable) { - q.choices = [wrapLocal()]; - return q; + name: 'socket_server', + message: 'Which socket server would you wanna connect to', + type: 'list', + choices: [] } - var maxShortLength = 0; + var wrapLocal = function () { + return { + value: (options.agent && options.agent.authorization ? options.agent.authorization + '@' : '') + '127.0.0.1:' + options.port, + short: 'localhost' + } + } + if (!remotable) { + q.choices = [wrapLocal()] + return q + } + var maxShortLength = 0 for (var remote in options.remotes) { - var connectionString = options.remotes[remote]; + var connectionString = options.remotes[remote] q.choices.push({ value: connectionString, short: remote - }); - maxShortLength = Math.max(maxShortLength, remote.length); + }) + maxShortLength = Math.max(maxShortLength, remote.length) } if (!options.agent.offline) { - var conn = wrapLocal(); - q.choices.push(conn); - maxShortLength = Math.max(maxShortLength, conn.short.length); + var conn = wrapLocal() + q.choices.push(conn) + maxShortLength = Math.max(maxShortLength, conn.short.length) } if (q.choices.length > 1) { q.choices.forEach(function (c) { - c.name = '[' + c.short + Array(maxShortLength - c.short.length + 1).join(options.blank || ' ') + '] ' + c.value; - }); + c.name = '[' + c.short + Array(maxShortLength - c.short.length + 1).join(options.blank || ' ') + '] ' + c.value + }) } - return q; -}; + return q +} /** * Convert connection object to string. @@ -617,13 +618,13 @@ Monitor.available = function (options) { */ Monitor.toConnectionString = function (connection) { var uri = (connection.protocol || 'http:') + '//' + (connection.hostname || '127.0.0.1') + ':' + connection.port + - (connection.path || '') + (connection.namespace || ''); + (connection.path || '') + (connection.namespace || '') if (connection.authorization) { - uri += (uri.indexOf('?') > 0 ? '&' : '?') + 'auth=' + connection.authorization; + uri += (uri.indexOf('?') > 0 ? '&' : '?') + 'auth=' + connection.authorization } - return uri; -}; + return uri +} /** * Parse connection string to an uri object. @@ -635,35 +636,35 @@ Monitor.parseConnectionString = function (connectionString) { port: 8088, hostname: '127.0.0.1', authorization: '' - }; - var lastAt = connectionString.lastIndexOf('@'); + } + var lastAt = connectionString.lastIndexOf('@') if (lastAt >= 0) { - connection.authorization = connectionString.slice(0, lastAt); - connectionString = connectionString.slice(lastAt + 1); + connection.authorization = connectionString.slice(0, lastAt) + connectionString = connectionString.slice(lastAt + 1) } if (!/^http(s)?:\/\//i.test(connectionString)) { - connectionString = 'http://' + connectionString; + connectionString = 'http://' + connectionString } if (connectionString) { - connectionString = url.parse(connectionString); - connection.hostname = connectionString.hostname; - connection.port = connectionString.port; - connection.path = _.trimLeft(connectionString.path, '/'); - connection.protocol = connectionString.protocol; + connectionString = url.parse(connectionString) + connection.hostname = connectionString.hostname + connection.port = connectionString.port + connection.path = _.trimLeft(connectionString.path, '/') + connection.protocol = connectionString.protocol } - return connection; -}; + return connection +} Object.defineProperty(Monitor.prototype, 'sockio', { set: function (io) { if (this._sockio) { - this._sockio.close(); + this._sockio.close() } - this._sockio = io; - this._listeningSocketIO(); + this._sockio = io + this._listeningSocketIO() }, get: function () { - return this._sockio; + return this._sockio } -}); +}) diff --git a/lib/pm.js b/lib/pm.js index 680a3fe..c9d0128 100644 --- a/lib/pm.js +++ b/lib/pm.js @@ -1,21 +1,18 @@ -var spawn = require('child_process').spawn, - fs = require('fs'), - path = require('path'), - _ = require('lodash'), - async = require('async'), - chalk = require('chalk'), - stat = require('./stat'), - rpc = require('pm2-axon-rpc'), - axon = require('pm2-axon'); +var spawn = require('child_process').spawn +var fs = require('fs') +var _ = require('lodash') +var async = require('async') +var rpc = require('pm2-axon-rpc') +var axon = require('pm2-axon') /** * Forever lib. * @type {{}} */ -var pm = module.exports = {}; +var pm = module.exports = {} -var re_blank = /^[\s\r\t]*$/, - allowedEvents = ['start', 'restart', 'exit', 'online']; +var re_blank = /^[\s\r\t]*$/ +var allowedEvents = ['start', 'restart', 'exit', 'online'] /** * Subscribe event BUS. @@ -24,24 +21,24 @@ var re_blank = /^[\s\r\t]*$/, * @param {Object} context */ pm.sub = function (sockPath, cb, context) { - var sub = axon.socket('sub-emitter'); + var sub = axon.socket('sub-emitter') // Once awake from sleeping. sub.on('log:*', function (e, d) { // Do not subscribe it. - sub.off('log:*'); - d.event = 'awake'; - cb.call(context, d); - }); + sub.off('log:*') + d.event = 'awake' + cb.call(context, d) + }) // Process events. sub.on('process:*', function (e, d) { if (d && !!~allowedEvents.indexOf(d.event)) { - cb.call(context, d); + cb.call(context, d) } - }); - sub.connect(sockPath); - return sub; -}; + }) + sub.connect(sockPath) + return sub +} /** * Get PM2 version. @@ -54,8 +51,8 @@ pm.version = function (sockPath, cb) { events: [ ['getVersion', {}, cb] ] - }); -}; + }) +} /** * List available processes. @@ -65,7 +62,7 @@ pm.version = function (sockPath, cb) { */ pm.list = function (sockPath, cb, context) { if (!fs.existsSync(sockPath)) { - return cb.call(context, []); + return cb.call(context, []) } pm._rpc({ sockPath: sockPath, @@ -73,8 +70,8 @@ pm.list = function (sockPath, cb, context) { ['getMonitorData', {}, cb] ], context: context || this - }); -}; + }) +} /** * Execute remote RPC events. @@ -88,38 +85,38 @@ pm.list = function (sockPath, cb, context) { * @private */ pm._rpc = function (opts) { - var req = axon.socket("req"), - rpcSock = req.connect(opts.sockPath), - rpcClient = new rpc.Client(req); + var req = axon.socket('req') + var rpcSock = req.connect(opts.sockPath) + var rpcClient = new rpc.Client(req) // Connect RPC server. rpcSock.on('connect', function () { // Execute request. var waterfalls = opts.events.map(function (event) { return function (next) { - var cb = typeof event[event.length - 1] == 'function' ? event.pop() : null; + var cb = typeof event[event.length - 1] === 'function' ? event.pop() : null if (cb) { event.push(function () { // Wrap arguments, no [].slice (avoid leak)!!! - var args = new Array(arguments.length); + var args = new Array(arguments.length) for (var i = 0; i < args; i++) { - args[i] = arguments[i]; + args[i] = arguments[i] } - cb.apply(opts.context, arguments); - next(); - }); + cb.apply(opts.context, arguments) + next() + }) } - rpcClient.call.apply(rpcClient, event); + rpcClient.call.apply(rpcClient, event) if (!cb) { - next(); + next() } - }; - }); - async.waterfall(waterfalls, function (err, res) { - rpcSock.close(); - }); - }); -}; + } + }) + async.waterfall(waterfalls, function () { + rpcSock.close() + }) + }) +} /** * Find process by pm_id. @@ -131,22 +128,22 @@ pm._rpc = function (opts) { pm._findById = function (sockPath, id, cb) { pm.list(sockPath, function (err, procs) { if (err) { - return cb(err); + return cb(err) } - if (!procs || procs.length == 0) { - return cb(new Error('No PM2 process running, the sockPath is "' + sockPath + '", please make sure it is existing!')); + if (!procs || procs.length === 0) { + return cb(new Error('No PM2 process running, the sockPath is "' + sockPath + '", please make sure it is existing!')) } var proc = _.find(procs, function (p) { - return p && p.pm_id == id; - }); + return p && p.pm_id === id + }) if (!proc) { - return cb(new Error('Cannot find pm process by pm_id: ' + id)); + return cb(new Error('Cannot find pm process by pm_id: ' + id)) } - cb(null, proc); - }, true); + cb(null, proc) + }, true) } /** @@ -156,28 +153,28 @@ pm._findById = function (sockPath, id, cb) { * @param {Function} cb */ pm.action = function (sockPath, action, id, cb) { - if (id == 'all') { + if (id === 'all') { pm.list(sockPath, function (err, procs) { if (err) { - return cb(err); + return cb(err) } - if (!procs || procs.length == 0) { - return cb(new Error('No PM2 process running, the sockPath is "' + sockPath + '", please make sure it is existing!')); + if (!procs || procs.length === 0) { + return cb(new Error('No PM2 process running, the sockPath is "' + sockPath + '", please make sure it is existing!')) } async.map(procs, function (proc, next) { - pm._actionByPMId(sockPath, proc, action, next.bind(null, null)); - }, cb); - }); + pm._actionByPMId(sockPath, proc, action, next.bind(null, null)) + }, cb) + }) } else { pm._findById(sockPath, id, function (err, proc) { if (err) { - return cb(err); + return cb(err) } - pm._actionByPMId(sockPath, proc, action, cb); - }); + pm._actionByPMId(sockPath, proc, action, cb) + }) } -}; +} /** * Trigger actions of process by pm_id. @@ -188,27 +185,27 @@ pm.action = function (sockPath, action, id, cb) { * @private */ pm._actionByPMId = function (sockPath, proc, action, cb) { - var noBusEvent = action == 'delete' && proc.pm2_env.status != 'online', - pm_id = proc.pm_id; + var noBusEvent = action === 'delete' && proc.pm2_env.status !== 'online' + var pm_id = proc.pm_id - action += 'ProcessId'; + action += 'ProcessId' var watchEvent = ['stopWatch', action, { id: pm_id - }, function (err, success) {}]; + }, function () {}] - if (!!~['restart'].indexOf(action)) { - watchEvent.splice(0, 1, 'restartWatch'); - watchEvent.pop(); + if (!!~['restart'].indexOf(action)) { // eslint-disable-line no-extra-boolean-cast + watchEvent.splice(0, 1, 'restartWatch') + watchEvent.pop() } var actionEvent = [action, pm_id, function (err, sock) { - cb(err, noBusEvent); - }]; + cb(err, noBusEvent) + }] - if (action == 'restartProcessId') { + if (action === 'restartProcessId') { actionEvent.splice(1, 1, { id: pm_id - }); + }) } pm._rpc({ @@ -217,8 +214,8 @@ pm._actionByPMId = function (sockPath, proc, action, cb) { watchEvent, actionEvent ] - }); -}; + }) +} /** * Tail logs. @@ -231,13 +228,13 @@ pm.tail = function (opts, each, cb) { // Fetch the proccess that we need. pm._findById(opts.sockPath, opts.pm_id, function (err, proc) { if (err) { - return cb(err); + return cb(err) } - proc.pm2_log = opts.logPath; + proc.pm2_log = opts.logPath // Tail logs. - cb(null, pm._tailLogs(proc, each)); - }); -}; + cb(null, pm._tailLogs(proc, each)) + }) +} /** * Use linux `tail` command to grep logs. * @param {Object} proc @@ -248,58 +245,58 @@ pm.tail = function (opts, each, cb) { pm._tailLogs = function (proc, cb) { var logs = { 'pm2': proc.pm2_log - }; + } if (proc.pm_log_path) { - logs.entire = proc.pm2_env.pm_log_path; + logs.entire = proc.pm2_env.pm_log_path } else { if (proc.pm2_env.pm_out_log_path) { - logs.out = proc.pm2_env.pm_out_log_path; + logs.out = proc.pm2_env.pm_out_log_path } if (proc.pm2_env.pm_err_log_path) { - logs.err = proc.pm2_env.pm_err_log_path; + logs.err = proc.pm2_env.pm_err_log_path } } - var logFiles = []; + var logFiles = [] for (var key in logs) { - var file = logs[key]; + var file = logs[key] if (fs.existsSync(file)) { - logFiles.push(file); + logFiles.push(file) } } - if (logFiles.length == 0) { - return null; + if (logFiles.length === 0) { + return null } var tail = spawn('tail', ['-n', 20, '-f'].concat(logFiles), { killSignal: 'SIGTERM', detached: true, stdio: ['ignore', 'pipe', 'pipe'] - }); + }) // Use utf8 encoding. tail.stdio.forEach(function (stdio) { - stdio && stdio.setEncoding('utf8'); - }); + stdio && stdio.setEncoding('utf8') + }) // stdout. tail.stdout.on('data', function (data) { - var lines = []; + var lines = [] data.split(/\n/).forEach(function (line) { if (!re_blank.test(line)) { - lines.push(line); + lines.push(line) } - }); + }) if (lines.length > 0) { - cb(null, lines); + cb(null, lines) } - }); + }) // handle error. tail.stderr.on('data', function (data) { - console.error(data.toString()); - tail.disconnect(); - cb(new Error(data.toString().replace(/\n/, ''))); - }); - tail.unref(); - return tail; -}; + console.error(data.toString()) + tail.disconnect() + cb(new Error(data.toString().replace(/\n/, ''))) + }) + tail.unref() + return tail +} diff --git a/lib/stat.js b/lib/stat.js index 9f0aad4..cecc446 100644 --- a/lib/stat.js +++ b/lib/stat.js @@ -1,4 +1,4 @@ -var os = require('os'); +var os = require('os') /** * System states @@ -25,28 +25,28 @@ var stat = module.exports = { * List all CPUs. * @returns {*} */ - get cpus() { - return os.cpus(); + get cpus () { + return os.cpus() }, /** * Uptime. * @returns {*} */ - get uptime() { - return os.uptime(); + get uptime () { + return os.uptime() }, /** * System memory usage. * @returns {{free: *, total: *, percentage: number}} */ - get memory() { + get memory () { return { free: os.freemem(), total: os.totalmem(), percentage: Math.round(100 * (1 - os.freemem() / os.totalmem())) } } -}; +} /** * System CPU usage percentage (total). @@ -55,28 +55,28 @@ var stat = module.exports = { */ stat.cpuUsage = function (fn, context) { setTimeout(function (ctx, stat1) { - var stat2 = ctx.cpuInfo(), - perc = 100 * (1 - (stat2.idle - stat1.idle) / (stat2.total - stat1.total)); - fn.call(context, null, perc.toFixed(2)); - }, 1000, this, this.cpuInfo()); -}; + var stat2 = ctx.cpuInfo() + var perc = 100 * (1 - (stat2.idle - stat1.idle) / (stat2.total - stat1.total)) + fn.call(context, null, perc.toFixed(2)) + }, 1000, this, this.cpuInfo()) +} /** * System CPU usage detail information. * @returns {{idle: number, total: number}} */ stat.cpuInfo = function () { - var cpus = this.cpus, - idle = 0, - total = 0; + var cpus = this.cpus + var idle = 0 + var total = 0 for (var i in cpus) { - idle += cpus[i].times.idle; + idle += cpus[i].times.idle for (var k in cpus[i].times) { - total += cpus[i].times[k]; + total += cpus[i].times[k] } } return { 'idle': idle, 'total': total - }; -}; + } +} diff --git a/lib/util/conf.js b/lib/util/conf.js index b7c72c2..9625f67 100644 --- a/lib/util/conf.js +++ b/lib/util/conf.js @@ -1,5 +1,10 @@ -var fs = require('fs'), - _ = require('lodash'); +var fs = require('fs') +var _ = require('lodash') + +var re_comment = /^\s*;/ +var re_setion = /^\s*\[([^\]]+)\]\s*$/ +var re_kv = /^([^=]+)=(.*)$/ +var re_boolean = /^(true|false)$/i /** * Namespaces of socket.io @@ -9,35 +14,35 @@ exports.NSP = { SYS: '/sys', LOG: '/log', PROC: '/proc' -}; +} /** * Configurations * @type {[type]} */ -exports.File = File; +exports.File = File /** * Configurations store in a disk file. * @param {Object} options * @constructor */ -function File(options) { +function File (options) { if (!(this instanceof File)) { - return new File(options); + return new File(options) } - if (typeof options == 'string') { + if (typeof options === 'string') { options = { file: options - }; + } } - options = _.assign({}, options || {}); + options = _.assign({}, options || {}) if (!options.file) { - throw new Error('`file` is required.'); + throw new Error('`file` is required.') } - Object.freeze(options); - this.options = options; + Object.freeze(options) + this.options = options } /** @@ -45,90 +50,85 @@ function File(options) { */ File.prototype.loadSync = function () { if (!fs.existsSync(this.options.file)) { - this._data = {}; - return this; + this._data = {} + return this } - var re_comment = /^\s*;/, - re_setion = /^\s*\[([^\]]+)\]\s*$/, - re_kv = /^([^=]+)=(.*)$/, - re_boolean = /^(true|false)$/i; - var json = {}, - sec; + var json = {} + var sec fs.readFileSync(this.options.file, { - encoding: 'utf8' - }) - .split(/[\r\n]/).forEach(function (line) { - // Empty line. - if (!line) { - sec = null; - return; - } - // Remove comments. - if (re_comment.test(line)) { - return; - } - var ms; - // Sections. - if ((ms = line.match(re_setion)) && ms.length == 2) { - json[sec = ms[1].trim()] = {}; - return; - } + encoding: 'utf8' + }).split(/[\r\n]/).forEach(function (line) { + // Empty line. + if (!line) { + sec = null + return + } + // Remove comments. + if (re_comment.test(line)) { + return + } + var ms + // Sections. + if ((ms = line.match(re_setion)) && ms.length === 2) { + json[sec = ms[1].trim()] = {} + return + } - // Key-value pairs. - if ((ms = line.match(re_kv)) && ms.length == 3) { - var key = ms[1].trim(), - value = ms[2].trim(); - // Parse boolean and number. - if (!isNaN(value)) { - value = parseFloat(value); - } else if (re_boolean.test(value)) { - value = value.toLowerCase() == 'true'; - } - if (sec) { - json[sec][key] = value; - } else { - json[key] = value; - } + // Key-value pairs. + if ((ms = line.match(re_kv)) && ms.length === 3) { + var key = ms[1].trim() + var value = ms[2].trim() + // Parse boolean and number. + if (!isNaN(value)) { + value = parseFloat(value) + } else if (re_boolean.test(value)) { + value = value.toLowerCase() === 'true' } - }); + if (sec) { + json[sec][key] = value + } else { + json[key] = value + } + } + }) - this._data = json; - return this; -}; + this._data = json + return this +} /** * Save data to a disk file (sync). * @returns {File} */ File.prototype.saveSync = function () { - function wrapValue(key, value) { - return key + ' = ' + (typeof value == 'string' ? value : JSON.stringify(value)) + '\n'; + function wrapValue (key, value) { + return key + ' = ' + (typeof value === 'string' ? value : JSON.stringify(value)) + '\n' } - var ini = ''; + var ini = '' for (var key in this._data) { - var value = this._data[key]; + var value = this._data[key] // TODO: Array type. - if (typeof value == 'object') { - ini += '[ ' + key + ' ]\n'; + if (typeof value === 'object') { + ini += '[ ' + key + ' ]\n' for (var subKey in value) { ini += wrapValue(subKey, value[subKey]) } - ini += '\n'; + ini += '\n' } - ini += wrapValue(key, value); + ini += wrapValue(key, value) } - fs.writeFileSync(this.options.file, ini); - return this; -}; + fs.writeFileSync(this.options.file, ini) + return this +} /** * Get data. * @returns {{}|*} */ File.prototype.valueOf = function () { - return this._data; -}; + return this._data +} /** * Get/set/remove key-value pairs. @@ -139,25 +139,27 @@ File.prototype.valueOf = function () { */ File.prototype.val = function (key, value, def) { if (!key) { - return; + return } // Load config from File. - this.loadSync(); + this.loadSync() - if (typeof value == 'undefined') { + if (typeof value === 'undefined') { // Get config. - return this._data[key]; + return this._data[key] } else if (value == null) { // Clear config. - delete this._data[key]; + delete this._data[key] // Reset to default if necessary. - (typeof def != 'undefined') && (this._data[key] = def); - return this.saveSync(); + if (typeof def !== 'undefined') { + this._data[key] = def + } + return this.saveSync() } - this._data[key] = value; + this._data[key] = value // Save it. - this.saveSync(); - return this; -}; + this.saveSync() + return this +} diff --git a/lib/util/log.js b/lib/util/log.js index 9822921..c26ef43 100644 --- a/lib/util/log.js +++ b/lib/util/log.js @@ -1,44 +1,44 @@ -var chalk = require('chalk'); +var chalk = require('chalk') module.exports = function (options) { - options = options || {}; - var lev = options.level, - hacks = ['debug', 'log', 'info', 'warn', 'error']; + options = options || {} + var lev = options.level + var hacks = ['debug', 'log', 'info', 'warn', 'error'] - if ((typeof lev == 'string' && typeof (lev = hacks.indexOf(lev)) == 'undefined') || (isFinite(lev) && (lev < 0 || lev > hacks.length))) { - options.level = 0; + if ((typeof lev === 'string' && typeof (lev = hacks.indexOf(lev)) === 'undefined') || (isFinite(lev) && (lev < 0 || lev > hacks.length))) { + options.level = 0 } - options.level = !isNaN(lev) ? lev : 0; + options.level = !isNaN(lev) ? lev : 0 - console.__level = options.level; + console.__level = options.level if (console.__hacked) { - return; + return } - var colors = ['grey', '', 'green', 'yellow', 'red'], - consoled = {}; + var colors = ['grey', '', 'green', 'yellow', 'red'] + var consoled = {} hacks.forEach(function (method) { - if (method == 'debug') { - consoled.debug = console.log; - return; + if (method === 'debug') { + consoled.debug = console.log + return } - consoled[method] = console[method]; - }); + consoled[method] = console[method] + }) hacks.forEach(function (method, index) { console[method] = function () { if (index < console.__level) { - return; + return } - if (method != 'log' && arguments.length > 0) { + if (method !== 'log' && arguments.length > 0) { arguments[0] = (options.prefix ? chalk.bold[colors[index]]('[' + method.toUpperCase() + '] ') : '') + - (options.date ? (new Date()).toLocaleString() + ' ' : '') + arguments[0]; + (options.date ? (new Date()).toLocaleString() + ' ' : '') + arguments[0] } - consoled[method].apply(console, arguments); - }; - }); + consoled[method].apply(console, arguments) + } + }) - console.__hacked = true; -}; + console.__hacked = true +} diff --git a/lib/util/router.js b/lib/util/router.js index 35c51a2..f4fe56d 100644 --- a/lib/util/router.js +++ b/lib/util/router.js @@ -1,44 +1,41 @@ -var _ = require('lodash'), - path = require('path'), - chalk = require('chalk'), - fs = require('fs'), - url = require('url'); +var path = require('path') +var fs = require('fs') var routes = [] // bind actions. -global.action = function(method, path, func){ - if (typeof method == 'function') { - func = method; - method = 'get'; - path = func.name; - } else if (typeof path == 'function') { - func = path; - path = func.name; +global.action = function (method, path, func) { + if (typeof method === 'function') { + func = method + method = 'get' + path = func.name + } else if (typeof path === 'function') { + func = path + path = func.name } - if (typeof method != 'string' || typeof path != 'string' || typeof func != 'function') { + if (typeof method !== 'string' || typeof path !== 'string' || typeof func !== 'function') { throw new Error('Arguments of action() should be one of `[FUNCTION]` / `[METHOD], [FUNCTION]` / `[METHOD], [PATH], [FUNCTION]`.') } routes.push({ method: method, - path : '/' + (!!~['index', 'home', 'main'].indexOf(__route_root) ? '' : __route_root) + (path ? '/' + path : ''), - fn : func - }); -}; + path: '/' + (!!~['index', 'home', 'main'].indexOf(__route_root) ? '' : __route_root) + (path ? '/' + path : ''), // eslint-disable-line no-extra-boolean-cast, no-undef + fn: func + }) +} -var _cwd = path.resolve(__dirname, '../../', 'web/routes'); +var _cwd = path.resolve(__dirname, '../../', 'web/routes') // initialize. -module.exports = function(server){ - fs.readdirSync(_cwd).forEach(function(f){ - if (path.extname(f) != '.js') { - return; +module.exports = function (server) { + fs.readdirSync(_cwd).forEach(function (f) { + if (path.extname(f) !== '.js') { + return } - global.__route_root = path.basename(f, '.js'); - require(path.resolve(_cwd, f)); - delete global.__route_root; - }); - routes.forEach(function(route){ - route.path = route.path.replace(/\/+/g, '/'); - server[route.method](route.path, route.fn); - }); -}; \ No newline at end of file + global.__route_root = path.basename(f, '.js') + require(path.resolve(_cwd, f)) + delete global.__route_root + }) + routes.forEach(function (route) { + route.path = route.path.replace(/\/+/g, '/') + server[route.method](route.path, route.fn) + }) +} diff --git a/package.json b/package.json index e92f4b9..d609da9 100644 --- a/package.json +++ b/package.json @@ -56,9 +56,12 @@ "standard": "*" }, "standard": { - "ignore": [], + "ignore": [ + "web/public/" + ], "globals": [ - "action" + "action", + "__route_root" ] }, "homepage": "https://github.com/Tjatse/pm2-gui" diff --git a/pm2-gui.ini b/pm2-gui.ini index eb6863c..188f14c 100644 --- a/pm2-gui.ini +++ b/pm2-gui.ini @@ -11,9 +11,13 @@ refresh = 5000 ; port = 8088 ; -; A value indicates whether run the pm2-gui damonized or not. +; A value indicates whether or not run the pm2-gui damonized. ; daemonize = true +; +; A value indicates whether or not the action buttons (i.e. `restart`, `stop all`...) should be displayed on web page. +; +readonly = true [log] ; @@ -21,11 +25,11 @@ daemonize = true ; dir = ./logs ; -; A value indicates whether display the [INFO], [ERROR].. prefixes before log message or not. +; A value indicates whether or not display the [INFO], [ERROR].. prefixes before log message. ; prefix = true ; -; A value indicates whether display the local date string before log message or not. +; A value indicates whether or not display the local date string before log message. ; date = false ; @@ -55,4 +59,12 @@ authorization = AuTh ; pm2@171 = AuTh@https://192.168.1.171:9002/sockserv ; pm2@172 = 192.168.1.172:9001 ; pm2@173 = 192.168.1.173:9000 -; \ No newline at end of file +; +spider_other = AuTh@192.168.100.79:8088 +spider_bbs = AuTh@192.168.100.78:8088 +spider_web = AuTh@192.168.100.77:8088 +level_web = AuTh@192.168.100.128:9009 +leve_bbs = AuTh@192.168.100.129:8088 +level_other = AuTh@192.168.100.130:8088 +spider_visionow = AuTh@192.168.100.138:8088 +spider_hst = AuTh@192.168.100.70:8088 \ No newline at end of file diff --git a/pm2-gui.js b/pm2-gui.js index aa4339f..ede5ffc 100644 --- a/pm2-gui.js +++ b/pm2-gui.js @@ -1,232 +1,231 @@ -var chalk = require('chalk'), - path = require('path'), - fs = require('fs'), - _ = require('lodash'), - socketIO = require('socket.io'), - inquirer = require("inquirer"), - conf = require('./lib/util/conf'), - Monitor = require('./lib/monitor'), - Log = require('./lib/util/log'), - Web = require('./web/index'), - layout = require('./lib/blessed-widget/layout'); +var chalk = require('chalk') +var path = require('path') +var fs = require('fs') +var _ = require('lodash') +var socketIO = require('socket.io') +var inquirer = require('inquirer') +var Monitor = require('./lib/monitor') +var Log = require('./lib/util/log') +var Web = require('./web/index') +var layout = require('./lib/blessed-widget/layout') -if (path.basename(process.mainModule.filename, '.js') == 'pm2-gui') { - var cmd, file; +if (path.basename(process.mainModule.filename, '.js') === 'pm2-gui') { + var cmd, file if (process.argv.length > 2) { - cmd = process.argv[2]; + cmd = process.argv[2] } if (process.argv.length > 3) { - file = process.argv[3]; + file = process.argv[3] } - cmd = cmd || 'start'; + cmd = cmd || 'start' switch (cmd) { - case 'start': - startWebServer(file); - break; - case 'agent': - startAgent(file); - break; - case 'mon': - dashboard(file); - break; - default: - Log({ - level: 0, - prefix: true - }); - console.error('Command', cmd, 'is not supported!') - break; + case 'start': + startWebServer(file) + break + case 'agent': + startAgent(file) + break + case 'mon': + dashboard(file) + break + default: + Log({ + level: 0, + prefix: true + }) + console.error('Command', cmd, 'is not supported!') + break } } -exports.startWebServer = startWebServer; -exports.startAgent = startAgent; -exports.dashboard = dashboard; -exports.exitGraceful = exitGraceful; +exports.startWebServer = startWebServer +exports.startAgent = startAgent +exports.dashboard = dashboard +exports.exitGraceful = exitGraceful -function startWebServer(confFile) { +function startWebServer (confFile) { var monitor = slave({ - confFile: confFile - }), - options = monitor.options; + confFile: confFile + }) + var options = monitor.options - options.port = options.port || 8088; + options.port = options.port || 8088 var server = Web({ middleware: function (req, res, next) { - req._config = options; - next(); + req._config = options + next() }, port: options.port - }); + }) monitor.sockio = socketIO(server, { origins: options.origins || '*:*' - }); - monitor.run(); - console.info('Web server is listening on 127.0.0.1:' + options.port); + }) + monitor.run() + console.info('Web server is listening on 127.0.0.1:' + options.port) } -function startAgent(confFile) { +function startAgent (confFile) { var monitor = slave({ confFile: confFile - }); + }) - var options = monitor.options; - options.agent = options.agent || {}; + var options = monitor.options + options.agent = options.agent || {} if (options.agent.offline) { - console.error('Agent is offline, can not start it.'); - return process.exit(0); + console.error('Agent is offline, can not start it.') + return process.exit(0) } - options.port = options.port || 8088; - var sockio = socketIO(); + options.port = options.port || 8088 + var sockio = socketIO() sockio.listen(options.port, { origins: options.origins || '*:*' - }); - monitor.sockio = sockio; - monitor.run(); - console.info('Socket.io server is listening on 0.0.0.0:' + options.port); + }) + monitor.sockio = sockio + monitor.run() + console.info('Socket.io server is listening on 0.0.0.0:' + options.port) } -function dashboard(confFile) { - // restore cursor; +function dashboard (confFile) { + // restore cursor process.on('exit', function () { - process.stdout.write('\u001b[?25h'); - }); + process.stdout.write('\u001b[?25h') + }) var monitor = slave({ - confFile: confFile - }), - options = _.clone(monitor.options), - q = Monitor.available(options); + confFile: confFile + }) + var options = _.clone(monitor.options) + var q = Monitor.available(options) if (!q) { - console.error('No agent is online, can not start it.'); - return process.exit(0); + console.error('No agent is online, can not start it.') + return process.exit(0) } - var ql = q.choices.length; - if (ql == 1) { - if (q.choices[0].short != 'localhost') { + var ql = q.choices.length + if (ql === 1) { + if (q.choices[0].short !== 'localhost') { console.info('There is just one remoting server online, try to connect it.') } - return _connectToDashboard(monitor, options, Monitor.parseConnectionString(q.choices[0].value)); + return _connectToDashboard(monitor, options, Monitor.parseConnectionString(q.choices[0].value)) } if (!options.agent || !options.agent.offline) { - q.choices.splice(ql - 1, 0, new inquirer.Separator()); + q.choices.splice(ql - 1, 0, new inquirer.Separator()) } console.info('Remoting servers are online, choose one you are intrested in.') - console.log(''); + console.log('') inquirer.prompt(q, function (answers) { - console.log(''); - _connectToDashboard(monitor, options, Monitor.parseConnectionString(answers.socket_server)); - }); + console.log('') + _connectToDashboard(monitor, options, Monitor.parseConnectionString(answers.socket_server)) + }) } -function exitGraceful(code, signal) { - code = code || 0; - if (signal != '-f') { - console.debug('Slave has exited, code: ' + code + ', signal: ' + (signal || 'NULL')); +function exitGraceful (code, signal) { + code = code || 0 + if (signal !== '-f') { + console.debug('Slave has exited, code: ' + code + ', signal: ' + (signal || 'NULL')) } - var fds = 0; + var fds = 0 - function tryToExit() { + function tryToExit () { if ((fds & 1) && (fds & 2)) { - process.exit(code); + process.exit(code) } } [process.stdout, process.stderr].forEach(function (std) { - var fd = std.fd; + var fd = std.fd if (!std.bufferSize) { - fds = fds | fd; + fds = fds | fd } else { std.write && std.write('', function () { - fds = fds | fd; - tryToExit(); - }); + fds = fds | fd + tryToExit() + }) } - }); - tryToExit(); + }) + tryToExit() } -function slave(options) { - process.title = 'pm2-gui slave'; - options = options || {}; - var confFile = options.confFile; +function slave (options) { + process.title = 'pm2-gui slave' + options = options || {} + var confFile = options.confFile if (!confFile) { - confFile = path.resolve(__dirname, './pm2-gui.ini'); + confFile = path.resolve(__dirname, './pm2-gui.ini') if (!fs.existsSync(confFile)) { - console.error(chalk.bold(confFile), 'does not exist!'); - return process.exit(0); + console.error(chalk.bold(confFile), 'does not exist!') + return process.exit(0) } } var monitor = Monitor({ confFile: confFile - }); + }) - Log(monitor.options.log); + Log(monitor.options.log) console.log(chalk.cyan( '\n' + '█▀▀█ █▀▄▀█ █▀█ ░░ ▒█▀▀█ ▒█░▒█ ▀█▀\n' + '█░░█ █░▀░█ ░▄▀ ▀▀ ▒█░▄▄ ▒█░▒█ ▒█░\n' + - '█▀▀▀ ▀░░░▀ █▄▄ ░░ ▒█▄▄█ ░▀▄▄▀ ▄█▄\n')); + '█▀▀▀ ▀░░░▀ █▄▄ ░░ ▒█▄▄█ ░▀▄▄▀ ▄█▄\n')) - process.on('SIGTERM', shutdown); - process.on('SIGINT', shutdown); - process.on('SIGHUP', restart); - process.on('uncaughtException', caughtException); + process.on('SIGTERM', shutdown) + process.on('SIGINT', shutdown) + process.on('SIGHUP', restart) + process.on('uncaughtException', caughtException) process.on('exit', exitGraceful) - function shutdown(code, signal) { - console.info('Shutting down....'); - monitor.quit(); - console.info('Shutdown complete!'); - exitGraceful(code, '-f'); + function shutdown (code, signal) { + console.info('Shutting down....') + monitor.quit() + console.info('Shutdown complete!') + exitGraceful(code, '-f') } - function restart() { + function restart () { if (process.send) { process.send({ action: 'restart' - }); + }) } else { - console.error('No IPC found, could not restart monitor, shutting down.'); - shutdown(1); + console.error('No IPC found, could not restart monitor, shutting down.') + shutdown(1) } } - function caughtException(err) { - console.error(err.stack); - shutdown(1); + function caughtException (err) { + console.error(err.stack) + shutdown(1) } - return monitor; + return monitor } -function _connectToDashboard(monitor, options, connection) { - connection = _.extend({}, options, connection); - if (!!~['127.0.0.1', '0.0.0.0', 'localhost'].indexOf(connection.hostname)) { +function _connectToDashboard (monitor, options, connection) { + connection = _.extend({}, options, connection) + if (!!~['127.0.0.1', '0.0.0.0', 'localhost'].indexOf(connection.hostname)) { // eslint-disable-line no-extra-boolean-cast return monitor.connect(connection, function (socket) { - console.info('Agent is online, try to connect it in dashboard directly.'); - layout(connection).render(monitor); + console.info('Agent is online, try to connect it in dashboard directly.') + layout(connection).render(monitor) }, function (err, socket) { - if (err == 'unauthorized') { - console.error('There was an error with the authentication:', err); - return process.exit(0); + if (err === 'unauthorized') { + console.error('There was an error with the authentication:', err) + return process.exit(0) } - console.warn('Agent is offline, try to start it.'); - var sockio = socketIO(); + console.warn('Agent is offline, try to start it.') + var sockio = socketIO() sockio.listen(connection.port, { origins: options.origins || '*:*' - }); - monitor.sockio = sockio; - monitor.run(); - layout(connection).render(monitor); - }); + }) + monitor.sockio = sockio + monitor.run() + layout(connection).render(monitor) + }) } - layout(connection).render(monitor); + layout(connection).render(monitor) } diff --git a/test/fixtures/colorful.js b/test/fixtures/colorful.js index 5aaa8d6..69cf0c8 100644 --- a/test/fixtures/colorful.js +++ b/test/fixtures/colorful.js @@ -1,14 +1,12 @@ -var chalk = require('chalk'); +var chalk = require('chalk') -console.log('This is', chalk.bold.red('red')); -console.log('This is', chalk.dim.green('green')); -console.log('This is', chalk.bold.green('green')); -console.log('This is', chalk.bold.italic.yellow('yellow')); -console.log('This is', chalk.bold.strikethrough.blue('blue')); -console.log('This is', chalk.bold.underline.magenta('magenta')); -console.log('This is', chalk.bold.cyan('cyan')); -console.log('This is', chalk.bold.grey('grey')); +console.log('This is', chalk.bold.red('red')) +console.log('This is', chalk.dim.green('green')) +console.log('This is', chalk.bold.green('green')) +console.log('This is', chalk.bold.italic.yellow('yellow')) +console.log('This is', chalk.bold.strikethrough.blue('blue')) +console.log('This is', chalk.bold.underline.magenta('magenta')) +console.log('This is', chalk.bold.cyan('cyan')) +console.log('This is', chalk.bold.grey('grey')) -setTimeout(function(){ - -}, 3000000); \ No newline at end of file +setTimeout(function () {}, 3000000) diff --git a/test/fixtures/exit.js b/test/fixtures/exit.js index 3e3afd3..f0ca461 100644 --- a/test/fixtures/exit.js +++ b/test/fixtures/exit.js @@ -1 +1 @@ -console.log('ok at', Date.now()); \ No newline at end of file +console.log('ok at', Date.now()) diff --git a/test/fixtures/fib-slow.js b/test/fixtures/fib-slow.js index 1b86182..1f445a8 100644 --- a/test/fixtures/fib-slow.js +++ b/test/fixtures/fib-slow.js @@ -1,13 +1,13 @@ -function fib(n){ - if (n == 1) return 1; - if (n == 0) return 0; +function fib (n) { + if (n === 1) return 1 + if (n === 0) return 0 if (n > 1) return fib(n - 2) + fib(n - 1) } -function fi(){ - console.log('fibonacci...'); - var f = fib((parseInt(Math.random() * 10000) + 30) % 42); - console.log('is:', f); - setTimeout(fi, 1000); +function fi () { + console.log('fibonacci...') + var f = fib((parseInt(Math.random() * 10000) + 30) % 42) + console.log('is:', f) + setTimeout(fi, 1000) } -fi(); +fi() diff --git a/test/fixtures/rand.js b/test/fixtures/rand.js index fe9081b..0117560 100644 --- a/test/fixtures/rand.js +++ b/test/fixtures/rand.js @@ -1,3 +1,3 @@ -setInterval(function(){ - console.log(Math.random()); -}, 3000); \ No newline at end of file +setInterval(function () { + console.log(Math.random()) +}, 3000) diff --git a/test/fixtures/throw.js b/test/fixtures/throw.js index 4149452..f9735c6 100644 --- a/test/fixtures/throw.js +++ b/test/fixtures/throw.js @@ -1,4 +1,4 @@ -console.log('App started.'); -setTimeout(function(){ - throw new Error('uncaughtException has been thrown.'); -}, 15000); \ No newline at end of file +console.log('App started.') +setTimeout(function () { + throw new Error('uncaughtException has been thrown.') +}, 15000) diff --git a/test/fixtures/tick.js b/test/fixtures/tick.js index 9c3f4a8..95dd5f4 100644 --- a/test/fixtures/tick.js +++ b/test/fixtures/tick.js @@ -1,4 +1,4 @@ -var chalk = require('chalk'); -setInterval(function(){ - console.log(chalk.bold.green('Tick'), Date.now()); -}, 1000); \ No newline at end of file +var chalk = require('chalk') +setInterval(function () { + console.log(chalk.bold.green('Tick'), Date.now()) +}, 1000) diff --git a/test/fixtures/tock.js b/test/fixtures/tock.js index 025b26f..a8b6d68 100644 --- a/test/fixtures/tock.js +++ b/test/fixtures/tock.js @@ -1,6 +1,6 @@ -var chalk = require('chalk'); +var chalk = require('chalk') -console.log(chalk.magenta('Tock every 5 seconds.')); -setInterval(function(){ - console.log(chalk.bold.red.underline('Tock'), Date.now()); -}, 5000); \ No newline at end of file +console.log(chalk.magenta('Tock every 5 seconds.')) +setInterval(function () { + console.log(chalk.bold.red.underline('Tock'), Date.now()) +}, 5000) diff --git a/web/index.js b/web/index.js index fbdce6e..cd16b91 100644 --- a/web/index.js +++ b/web/index.js @@ -1,28 +1,27 @@ -var express = require('express'), - session = require('express-session'), - path = require('path'), - http = require('http'), - Monitor = require('../lib/monitor'), - router = require('../lib/util/router'); +var express = require('express') +var session = require('express-session') +var path = require('path') +var http = require('http') +var router = require('../lib/util/router') -module.exports = runServer; +module.exports = runServer -function runServer(options) { - var app = express(); - app.set('view engine', 'jade'); - app.set('views', path.join(__dirname, 'templates/views')); - app.use(express.static(path.join(__dirname, 'public'))); +function runServer (options) { + var app = express() + app.set('view engine', 'jade') + app.set('views', path.join(__dirname, 'templates/views')) + app.use(express.static(path.join(__dirname, 'public'))) app.use(session({ secret: 'pm2@gui', resave: false, saveUninitialized: true - })); + })) if (options.middleware) { - app.use(options.middleware); + app.use(options.middleware) } - router(app); + router(app) - var server = http.Server(app); - server.listen(options.port); - return server; + var server = http.Server(app) + server.listen(options.port) + return server } diff --git a/web/routes/index.js b/web/routes/index.js index 18dc84e..34d4d08 100644 --- a/web/routes/index.js +++ b/web/routes/index.js @@ -1,58 +1,57 @@ -var Monitor = require('../../lib/monitor'), - _ = require('lodash'); +var _ = require('lodash') +var Monitor = require('../../lib/monitor') // Authorization -action(function auth(req, res) { +action(function auth (req, res) { if (!req._config.agent || (req._config.agent.authorization === req.session['authorization'])) { - return res.redirect('/'); + return res.redirect('/') } res.render('auth', { title: 'Authorization' - }); -}); + }) +}) // Index action(function (req, res) { - var auth; - if (req._config.agent && ((auth = req._config.agent.authorization) !== req.session['authorization'])) { - return res.redirect('/auth'); + if (req._config.agent && (req._config.agent.authorization !== req.session['authorization'])) { + return res.redirect('/auth') } - var options = _.clone(req._config), - q = Monitor.available(_.extend(options, { - blank: ' ' - })), - connections = []; + var options = _.clone(req._config) + var q = Monitor.available(_.extend(options, { + blank: ' ' + })) + var connections = [] q.choices.forEach(function (c) { - c.value = Monitor.toConnectionString(Monitor.parseConnectionString(c.value)); - connections.push(c); - }); + c.value = Monitor.toConnectionString(Monitor.parseConnectionString(c.value)) + connections.push(c) + }) res.render('index', { title: 'Monitor', connections: connections - }); -}); + }) +}) // API -action(function auth_api(req, res) { +action(function auth_api (req, res) { if (!req._config.agent || !req._config.agent.authorization) { return res.json({ error: 'Can not found agent[.authorization] config, no need to authorize!' - }); + }) } if (!req.query || !req.query.authorization) { return res.json({ error: 'Authorization is required!' - }); + }) } if (req._config.agent && req.query.authorization === req._config.agent.authorization) { - req.session['authorization'] = req.query.authorization; + req.session['authorization'] = req.query.authorization return res.json({ status: 200 - }); + }) } return res.json({ error: 'Failed, authorization is incorrect.' - }); -}); + }) +})