starter.js 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. var cp = require('child_process');
  2. var logger = require('pomelo-logger').getLogger('pomelo', __filename);
  3. var starter = module.exports;
  4. var util = require('util');
  5. var utils = require('../util/utils');
  6. var Constants = require('../util/constants');
  7. var env = Constants.RESERVED.ENV_DEV;
  8. var os = require('os');
  9. var cpus = {};
  10. var pomelo = require('../pomelo');
  11. /**
  12. * Run all servers
  13. *
  14. * @param {Object} app current application context
  15. * @return {Void}
  16. */
  17. starter.runServers = function (app) {
  18. var server, servers;
  19. var condition = app.startId || app.type;
  20. switch (condition) {
  21. case Constants.RESERVED.MASTER:
  22. break;
  23. case Constants.RESERVED.ALL:
  24. servers = app.getServersFromConfig();
  25. for (var serverId in servers) {
  26. this.run(app, servers[serverId]);
  27. }
  28. break;
  29. default:
  30. server = app.getServerFromConfig(condition);
  31. if (!!server) {
  32. this.run(app, server);
  33. } else {
  34. servers = app.get(Constants.RESERVED.SERVERS)[condition];
  35. for (var i = 0; i < servers.length; i++) {
  36. this.run(app, servers[i]);
  37. }
  38. }
  39. }
  40. };
  41. /**
  42. * Run server
  43. *
  44. * @param {Object} app current application context
  45. * @param {Object} server
  46. * @return {Void}
  47. */
  48. starter.run = function (app, server, cb) {
  49. env = app.get(Constants.RESERVED.ENV);
  50. var cmd, key;
  51. if (utils.isLocal(server.host)) {
  52. var options = [];
  53. if (!!server.args) {
  54. if (typeof server.args === 'string') {
  55. options.push(server.args.trim());
  56. } else {
  57. options.push(server.args);
  58. }
  59. }
  60. cmd = app.get(Constants.RESERVED.MAIN);
  61. options.push(cmd);
  62. options.push(util.format('env=%s', env));
  63. for (key in server) {
  64. if (key === Constants.RESERVED.CPU) {
  65. cpus[server.id] = server[key];
  66. }
  67. options.push(util.format('%s=%s', key, server[key]));
  68. }
  69. starter.localrun(process.execPath, null, options, cb);
  70. } else {
  71. cmd = util.format('cd "%s" && "%s"', app.getBase(), process.execPath);
  72. var arg = server.args;
  73. if (arg !== undefined) {
  74. cmd += arg;
  75. }
  76. cmd += util.format(' "%s" env=%s ', app.get(Constants.RESERVED.MAIN), env);
  77. for (key in server) {
  78. if (key === Constants.RESERVED.CPU) {
  79. cpus[server.id] = server[key];
  80. }
  81. cmd += util.format(' %s=%s ', key, server[key]);
  82. }
  83. starter.sshrun(cmd, server.host, cb);
  84. }
  85. };
  86. /**
  87. * Bind process with cpu
  88. *
  89. * @param {String} sid server id
  90. * @param {String} pid process id
  91. * @param {String} host server host
  92. * @return {Void}
  93. */
  94. starter.bindCpu = function (sid, pid, host) {
  95. if (os.platform() === Constants.PLATFORM.LINUX && cpus[sid] !== undefined) {
  96. if (utils.isLocal(host)) {
  97. var options = [];
  98. options.push('-pc');
  99. options.push(cpus[sid]);
  100. options.push(pid);
  101. starter.localrun(Constants.COMMAND.TASKSET, null, options);
  102. }
  103. else {
  104. var cmd = util.format('taskset -pc "%s" "%s"', cpus[sid], pid);
  105. starter.sshrun(cmd, host, null);
  106. }
  107. }
  108. };
  109. /**
  110. * Kill application in all servers
  111. *
  112. * @param {String} pids array of server's pid
  113. * @param {String} serverIds array of serverId
  114. */
  115. starter.kill = function (pids, servers) {
  116. var cmd;
  117. for (var i = 0; i < servers.length; i++) {
  118. var server = servers[i];
  119. if (utils.isLocal(server.host)) {
  120. var options = [];
  121. if (os.platform() === Constants.PLATFORM.WIN) {
  122. cmd = Constants.COMMAND.TASKKILL;
  123. options.push('/pid');
  124. options.push('/f');
  125. } else {
  126. cmd = Constants.COMMAND.KILL;
  127. options.push(-9);
  128. }
  129. options.push(pids[i]);
  130. starter.localrun(cmd, null, options);
  131. } else {
  132. if (os.platform() === Constants.PLATFORM.WIN) {
  133. cmd = util.format('taskkill /pid %s /f', pids[i]);
  134. } else {
  135. cmd = util.format('kill -9 %s', pids[i]);
  136. }
  137. starter.sshrun(cmd, server.host);
  138. }
  139. }
  140. };
  141. /**
  142. * Use ssh to run command.
  143. *
  144. * @param {String} cmd command that would be executed in the remote server
  145. * @param {String} host remote server host
  146. * @param {Function} cb callback function
  147. *
  148. */
  149. starter.sshrun = function (cmd, host, cb) {
  150. var args = [];
  151. args.push(host);
  152. var ssh_params = pomelo.app.get(Constants.RESERVED.SSH_CONFIG_PARAMS);
  153. if (!!ssh_params && Array.isArray(ssh_params)) {
  154. args = args.concat(ssh_params);
  155. }
  156. args.push(cmd);
  157. logger.info('Executing ' + cmd + ' on ' + host + ':22');
  158. spawnProcess(Constants.COMMAND.SSH, host, args, cb);
  159. return;
  160. };
  161. /**
  162. * Run local command.
  163. *
  164. * @param {String} cmd
  165. * @param {Callback} callback
  166. *
  167. */
  168. starter.localrun = function (cmd, host, options, callback) {
  169. logger.info('Executing ' + cmd + ' ' + options + ' locally');
  170. spawnProcess(cmd, host, options, callback);
  171. };
  172. /**
  173. * Fork child process to run command.
  174. *
  175. * @param {String} command
  176. * @param {Object} options
  177. * @param {Callback} callback
  178. *
  179. */
  180. var spawnProcess = function (command, host, options, cb) {
  181. var child = null;
  182. var id = null;
  183. for (let index = 0; index < options.length; index++) {
  184. const element = options[index];
  185. if (element.indexOf('--debug') >= 0) {
  186. options[index] = element.replace('--debug', '--inspect');
  187. }
  188. if(element.indexOf('id=') >= 0){
  189. id = element;
  190. }
  191. }
  192. if (env === Constants.RESERVED.ENV_DEV) {
  193. child = cp.spawn(command, options);
  194. logger.info('spawn', id, child.pid);
  195. var prefix = command === Constants.COMMAND.SSH ? '[' + host + '] ' : '';
  196. child.stderr.on('data', function (chunk) {
  197. var msg = chunk.toString();
  198. process.stderr.write(msg);
  199. if (!!cb) {
  200. cb(msg);
  201. }
  202. });
  203. child.stdout.on('data', function (chunk) {
  204. var msg = prefix + chunk.toString();
  205. process.stdout.write(msg);
  206. });
  207. } else {
  208. child = cp.spawn(command, options, { detached: true, stdio: 'inherit' });
  209. child.unref();
  210. }
  211. child.on('exit', function (code) {
  212. if (code !== 0) {
  213. logger.warn('child process exit with error, error code: %s, executed command: %s %s', code, command, options);
  214. }
  215. if (typeof cb === 'function') {
  216. cb(code === 0 ? null : code);
  217. }
  218. });
  219. };