UNPKG

fis3-command-server

Version:
205 lines (170 loc) 5.67 kB
var server = module.exports; var options = server._options = {}; var spawn = require('child_process').spawn; var util = require('./util.js'); var _ = fis.util; var qrcode = require('qrcode-terminal'); server.options = function(opts) { if (arguments.length) { _.assign(options, opts); } else { return options; } }; // 加载插件,启动服务。 function start() { var app = fis.require('server', options.type); util.serverInfo(options); app.start(options, function(error, info) { if (error) { fis.log.throw = false; fis.log.error('fail to start server.\n\n %s', error); return; } var address = (options.https ? 'https' : 'http') + '://127.0.0.1' + (options.port == 80 ? '/' : ':' + options.port + '/'); fis.log.notice('Browse %s', address.yellow.bold); fis.log.notice('Or browse %s', ((options.https ? 'https' : 'http') + '://' + util.hostname + (options.port == 80 ? '/' : ':' + options.port + '/')).yellow.bold); console.log(); options.qrcode && qrcode.generate((options.https ? 'https' : 'http') + '://' + util.hostname + (options.port == 80 ? '/' : ':' + options.port + '/')); setTimeout(function() { options.browse ? util.open(address, function() { options.daemon && process.exit(); }) : (options.daemon && process.exit()); }, 200); }); } // 根据 pid 检测子进程是否存在。 function checkPid(pid, callback) { var list, msg = ''; var isWin = _.isWin(); var serverInfo = util.serverInfo() || options; if (isWin) { list = spawn('tasklist'); } else { list = spawn('ps', ['-A']); } list.stdout.on('data', function(chunk) { msg += chunk.toString('utf-8').toLowerCase(); }); list.on('exit', function() { var found = false; msg.split(/[\r\n]+/).forEach(function(item) { if (~item.indexOf('--type ' + serverInfo.type) || process.platform !== 'darwin') { var m = item.match(/\d+/); if (m && m[0] == pid) { found = true; } } }); callback(found); }); list.on('error', function(e) { if (isWin) { fis.log.error('fail to execute `tasklist` command, please add your system path (eg: C:\\Windows\\system32, you should replace `C` with your system disk) in %PATH%'); } else { fis.log.error('fail to execute `ps` command.'); } }); } // 停止服务。 function stop(callback) { var pidFile = util.getPidFile(); var isWin = _.isWin(); var pid = util.pid(); if (pid) { checkPid(pid, function(exists) { if (exists) { if (isWin) { // windows 貌似没有 gracefully 关闭。 // 用 process.kill 会遇到进程关不了的情况,没有 exit 事件响应,原因不明! require('child_process').exec('taskkill /PID ' + pid + ' /T /F'); } else { // try to gracefully kill it. process.kill(pid, 'SIGTERM'); } // checkout it every half second. (function(done) { var start = Date.now(); var timer = setTimeout(function() { var fn = arguments.callee; checkPid(pid, function(exists) { if (exists) { // 实在关不了,那就野蛮的关了它。 if (Date.now() - start > 5000) { try { isWin ? require('child_process').exec('taskkill /PID ' + pid + ' /T /F') : process.kill(pid, 'SIGKILL'); } catch (e) { // I dont care the error. } clearTimeout(timer); done(); return; } timer = setTimeout(fn, 500); } else { done(); } }); }, 20); })(function() { fis.log.info('Shutdown with pid [%s]', pid); util.pid(0); callback && callback(null, true); }); } else { callback && callback(null, false); } }); } else { // pid 文件不存在,说明没有开启服务。 callback && callback(null, false); } } server.start = function() { // 如果是非后台运行模式,则 if (!options.daemon) { start(); } else { stop(start); } }; server.stop = function(callback) { stop(function(error, stoped) { if (!stoped) { fis.log.warn('The server is not runing.'); } callback && callback.apply(this, arguments); }); }; // 输出服务器配置信息。 server.info = function() { var serverInfo = util.serverInfo() || options; console.log(); // 输出个空行。 util.printObject(serverInfo, ' '); }; // 打开服务器根目录。 server.open = function() { var serverInfo = util.serverInfo() || options; fis.log.notice('Browse %s\n', serverInfo.root.yellow.bold); util.open(serverInfo.root); }; // 清空服务器目录。 server.clean = function() { var now = Date.now(); var serverInfo = util.serverInfo() || options; process.stdout.write('\n δ '.bold.yellow); try { var app = fis.require('server', options.type); if (app.clean) { app.clean(serverInfo); } else { fis.util.del(serverInfo.root, options.include || fis.get('server.clean.include'), options.exclude || fis.get('server.clean.exclude', 'server.log')); } } catch (e) { fis.util.del(serverInfo.root, options.include || fis.get('server.clean.include'), options.exclude || fis.get('server.clean.exclude', 'server.log')); } process.stdout.write((Date.now() - now + 'ms').green.bold); process.stdout.write('\n'); };