UNPKG

omelop

Version:

[![Build Status](https://travis-ci.org/node-omelop/omelop.svg?branch=master)](https://travis-ci.org/node-omelop/omelop)

236 lines 16.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.localrun = exports.sshrun = exports.kill = exports.bindCpu = exports.run = exports.runServers = void 0; const cp = require("child_process"); const omelop_logger_1 = require("omelop-logger"); const util = require("util"); const utils = require("../util/utils"); const Constants = require("../util/constants"); const os = require("os"); const omelop_1 = require("../omelop"); const path = require("path"); let logger = (0, omelop_logger_1.getLogger)('omelop', path.basename(__filename)); let cpus = {}; let env = Constants.RESERVED.ENV_DEV; /** * Run all servers * * @param {Object} app current application context * @return {Void} */ function runServers(app) { let server, servers; let condition = app.startId || app.type; switch (condition) { case Constants.RESERVED.MASTER: break; case Constants.RESERVED.ALL: servers = app.getServersFromConfig(); for (let serverId in servers) { run(app, servers[serverId]); } break; default: server = app.getServerFromConfig(condition); if (!!server) { run(app, server); } else { servers = app.get(Constants.RESERVED.SERVERS)[condition]; for (let i = 0; i < servers.length; i++) { run(app, servers[i]); } } } } exports.runServers = runServers; /** * Run server * * @param {Object} app current application context * @param {Object} server * @return {Void} */ function run(app, server, cb) { env = app.get(Constants.RESERVED.ENV); let cmd, key; if (utils.isLocal(server.host)) { let options = []; if (!!server.args) { if (typeof server.args === 'string') { options.push(server.args.trim()); } else { options = options.concat(server.args); } } cmd = app.get(Constants.RESERVED.MAIN); options.push(cmd); options.push(util.format('env=%s', env)); for (key in server) { if (key === Constants.RESERVED.CPU) { cpus[server.id] = server[key]; } options.push(util.format('%s=%s', key, server[key]).toString()); } localrun(process.execPath, null, options, cb); } else { cmd = util.format('cd "%s" && "%s"', app.getBase(), process.execPath); let arg = server.args; if (arg !== undefined) { if (typeof arg === 'string') { cmd += ' ' + arg.trim(); } else { for (let v of arg) { cmd += ' ' + v.trim(); } } } cmd += util.format(' "%s" env=%s ', app.get(Constants.RESERVED.MAIN), env); for (key in server) { if (key === Constants.RESERVED.CPU) { cpus[server.id] = server[key]; } cmd += util.format(' %s=%s ', key, server[key].toString()); } sshrun(cmd, server.host, cb); } } exports.run = run; /** * Bind process with cpu * * @param {String} sid server id * @param {String} pid process id * @param {String} host server host * @return {Void} */ function bindCpu(sid, pid, host) { if (os.platform() === Constants.PLATFORM.LINUX && cpus[sid] !== undefined) { if (utils.isLocal(host)) { let options = []; options.push('-pc'); options.push(String(cpus[sid])); options.push(pid); localrun(Constants.COMMAND.TASKSET, null, options); } else { let cmd = util.format('taskset -pc "%s" "%s"', cpus[sid], pid); sshrun(cmd, host, null); } } } exports.bindCpu = bindCpu; /** * Kill application in all servers * * @param {String} pids array of server's pid * @param {String} serverIds array of serverId */ function kill(pids, servers) { let cmd; for (let i = 0; i < servers.length; i++) { let server = servers[i]; if (utils.isLocal(server.host)) { let options = []; if (os.platform() === Constants.PLATFORM.WIN) { cmd = Constants.COMMAND.TASKKILL; options.push('/pid'); options.push('/f'); } else { cmd = Constants.COMMAND.KILL; options.push(String(-9)); } options.push(pids[i]); localrun(cmd, null, options); } else { if (os.platform() === Constants.PLATFORM.WIN) { cmd = util.format('taskkill /pid %s /f', pids[i]); } else { cmd = util.format('kill -9 %s', pids[i]); } sshrun(cmd, server.host); } } } exports.kill = kill; /** * Use ssh to run command. * * @param {String} cmd command that would be executed in the remote server * @param {String} host remote server host * @param {Function} cb callback function * */ function sshrun(cmd, host, cb) { let args = []; args.push(host); // omelop masterha 命令下pinus.app为undefined if (omelop_1.omelop.app) { let ssh_params = omelop_1.omelop.app.get(Constants.RESERVED.SSH_CONFIG_PARAMS); if (!!ssh_params && Array.isArray(ssh_params)) { args = args.concat(ssh_params); } } args.push(cmd); logger.info('Executing ' + cmd + ' on ' + host + ':22'); spawnProcess(Constants.COMMAND.SSH, host, args, cb); return; } exports.sshrun = sshrun; /** * Run local command. * * @param {String} cmd * @param {Callback} callback * */ function localrun(cmd, host, options, callback) { logger.info('Executing ' + cmd + ' ' + options + ' locally'); spawnProcess(cmd, host, options, callback); } exports.localrun = localrun; /** * Fork child process to run command. * * @param {String} command * @param {Object} options * @param {Callback} callback * */ let spawnProcess = function (command, host, options, cb) { let child = null; if (env === Constants.RESERVED.ENV_DEV) { child = cp.spawn(command, options); let prefix = command === Constants.COMMAND.SSH ? '[' + host + '] ' : ''; child.stderr.on('data', function (chunk) { let msg = chunk.toString(); process.stderr.write(msg); if (!!cb) { cb(msg); } }); child.stdout.on('data', function (chunk) { let msg = prefix + chunk.toString(); process.stdout.write(msg); }); } else { child = cp.spawn(command, options, { detached: true, stdio: 'inherit' }); child.unref(); } child.on('exit', function (code) { if (code !== 0) { logger.warn('child process exit with error, error code: %s, executed command: %s', code, command); } if (typeof cb === 'function') { cb(code === 0 ? null : code); } }); }; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic3RhcnRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9tYXN0ZXIvc3RhcnRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxvQ0FBb0M7QUFDcEMsaURBQTBDO0FBQzFDLDZCQUE2QjtBQUM3Qix1Q0FBdUM7QUFDdkMsK0NBQStDO0FBRS9DLHlCQUF5QjtBQUN6QixzQ0FBbUM7QUFFbkMsNkJBQTZCO0FBRTdCLElBQUksTUFBTSxHQUFHLElBQUEseUJBQVMsRUFBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFFBQVEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDO0FBRzVELElBQUksSUFBSSxHQUFtQyxFQUFFLENBQUM7QUFDOUMsSUFBSSxHQUFHLEdBQVcsU0FBUyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7QUFFN0M7Ozs7O0dBS0c7QUFDSCxTQUFnQixVQUFVLENBQUMsR0FBZ0I7SUFDdkMsSUFBSSxNQUFNLEVBQUUsT0FBTyxDQUFDO0lBQ3BCLElBQUksU0FBUyxHQUFHLEdBQUcsQ0FBQyxPQUFPLElBQUksR0FBRyxDQUFDLElBQUksQ0FBQztJQUN4QyxRQUFRLFNBQVMsRUFBRTtRQUNmLEtBQUssU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNO1lBQzFCLE1BQU07UUFDVixLQUFLLFNBQVMsQ0FBQyxRQUFRLENBQUMsR0FBRztZQUN2QixPQUFPLEdBQUcsR0FBRyxDQUFDLG9CQUFvQixFQUFFLENBQUM7WUFDckMsS0FBSyxJQUFJLFFBQVEsSUFBSSxPQUFPLEVBQUU7Z0JBQzFCLEdBQUcsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUM7YUFDL0I7WUFDRCxNQUFNO1FBQ1Y7WUFDSSxNQUFNLEdBQUcsR0FBRyxDQUFDLG1CQUFtQixDQUFDLFNBQVMsQ0FBQyxDQUFDO1lBQzVDLElBQUksQ0FBQyxDQUFDLE1BQU0sRUFBRTtnQkFDVixHQUFHLENBQUMsR0FBRyxFQUFFLE1BQU0s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