pomelo start命令的背后-pomelo源码分析(1)

pomelo start命令的背后-pomelo源码分析(1)

首先,$which pomelo发现全局的pomelo命令指向的是/usr/local/bin/pomelo文件,该文件是/usr/local/lib/node_modules/pomelo/bin/pomelo文件的软链接,直接查看该文件的内容,我们发现这个pomelo其实就是一个js文件。而且头一行为:屏幕快照 2015-04-21 下午5.42.59 ,这句话表示告诉系统,我们要调用node进程来执行pomelo这个js脚本文件。$pomelo start = $node /usr/local/bin/pomelo$pomelo start -D = $node /usr/local/bin/pomelo start -D

再往下看,有这么一段代码:

program.command('start')
  .description('start the application')
  .option('-e, --env <env>', 'the used environment', DEFAULT_ENV)
  .option('-D, --daemon', 'enable the daemon start')
  .option('-d, --directory, <directory>', 'the code directory', DEFAULT_GAME_SERVER_DIR)
  .option('-t, --type <server-type>,', 'start server type')
  .option('-i, --id <server-id>', 'start server id')
  .action(function(opts) {
    start(opts);
  });

这是Node.js的commander模块的用法,commander模块比Node.js内置的process.argv强大得多,具体用法自己百度。上面这段代码很容易理解,就是对start参数,调用下面这个start(opts)函数。

function start(opts) {
  var absScript = path.resolve(opts.directory, 'app.js'); // 获得app.js的绝对路径(默认当前路径下app.js)
  if (!fs.existsSync(absScript)) {
    abort(SCRIPT_NOT_FOUND);
  } // 如果不存在app.js文件,打印错误并终止程序

  var logDir = path.resolve(opts.directory, 'logs'); // 获得logs目录(默认为当前路径下的logs)
  if (!fs.existsSync(logDir)) {
    fs.mkdir(logDir);
  } // 不存在则新建该目录
  
  var ls;
  var type = opts.type || constants.RESERVED.ALL; // 默认得到type=all (就是要启动master进程)
  var params = [absScript, 'env=' + opts.env, 'type=' + type]; // 至此默认会得到params = ['/当前绝对路径/app.js', 'env = development', 'type=all']
  if(!!opts.id) {
    params.push('startId=' + opts.id);
  } 
  if (opts.daemon) { // 是否启用守护进程模式
    ls = spawn(process.execPath, params, {detached: true, stdio: 'ignore'}); // 已守护进程方式生成子进程
    ls.unref();
    console.log(DAEMON_INFO);
    process.exit(0); // 父进程退出
  } else {
    ls = spawn(process.execPath, params);  // 调用Node.js内置的child_process.spawn()方法生成子进程,并返回子进程对象
                                           // ==> "node /当前绝对路径/app.js env = development type=all"
    ls.stdout.on('data', function(data) {
      console.log(data.toString());
    }); // 打印将子进程的标准输出
    ls.stderr.on('data', function(data) {
      console.log(data.toString());
    }); // 打印子进程的错误输出
  }
}

最后让我们来实际验证一下上面的结论。在game-server目录下执行$pomelo start,然后再开一种终端检查$ps -ef|grep node,你会发现有如下两个进程:屏幕快照 2015-04-21 下午8.59.23

2093 号进程"node /usr/local/bin/pomelo start" 就是 pomelo start进程,它负责解析pomelo start命令的参数,然后生成2094号子进程"/usr/.../node /Users/.../app.js env=development type=all"。这个子进程就是pomelo服务器进程组中的master服务进程,它又负责生成gate、connector等子服务器进程。

Leave a Reply

Your email address will not be published. Required fields are marked *