首先,$which pomelo发现全局的pomelo命令指向的是/usr/local/bin/pomelo文件,该文件是/usr/local/lib/node_modules/pomelo/bin/pomelo文件的软链接,直接查看该文件的内容,我们发现这个pomelo其实就是一个js文件。而且头一行为: ,这句话表示告诉系统,我们要调用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,你会发现有如下两个进程:
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等子服务器进程。