egg-scripts
在package.json文件中加入如下两个脚本命令:
"scripts": {
//..
"start": "egg-scripts start --port=7002 --daemon --title=egg-server-showcase --DEBUG=common-bin --workders 1",
"stop": "egg-scripts stop",
},
其中‘–daemon’表示以守护进程方式运行,‘–DEBUG=common-bin’指定debug模块的输出类型为‘common-bin’,不属于‘common-bin’类型的信息将不会打印,‘–workders 1 ’指定app进程的fork数量为1,默认为计算机内核数量。
运行‘npm run start’ 或 ‘npm run stop’命令时,npm会在node_modules/.bin下寻找egg-scripts可执行文件并执行。node_modules/.bin/egg-scripts被软链接到node_modules/egg-scripts/bin/egg-scripts.js文件。egg-scripts.js会实例化EggScripts类,并调用实例的start()方法来启动整个框架。
EggScripts继承Command,Command继承BaseCommand。BaseCommand即common-bin模块的CommonBin类,common-bin模块是一个用于创建(在命令行执行的)命令的模块,封装的功能包括显示help信息等。CommonBin的load()方法用来加载子命令,* DISPATCH方法用来执行子命令(通过调用子命令的run方法),start()方法用来解析命令行参数并调用[DISPATCH]方法来执行参数中的子命令:
//node_modules/common-bin/lib/command.js class CommonBin{}
start() {
co(function* () {
// replace `--get-yargs-completions` to our KEY, so yargs will not block our DISPATCH
const index = this.rawArgv.indexOf('--get-yargs-completions');
if (index !== -1) {
// bash will request as `--get-yargs-completions my-git remote add`, so need to remove 2
this.rawArgv.splice(index, 2, `--AUTO_COMPLETIONS=${
this.rawArgv.join(',')}`);
}
yield this[DISPATCH]();
}.bind(this)).catch(this.errorHandler.bind(this));
}
egg-scripts包含了StartCommand(node_modules/egg-scripts/lib/cmd/start.js)和StopCommand(node_modules/egg-scripts/lib/cmd/stop.js)两个子命令,两个子命令都继承Command,需要执行的任务都写在函数* run()中。StartCommand中运行守护进程的代码如下,spawn一个子进程,在egg启动完成之后断开连接并让父进程退出。这里的eggArgs的第一个值是‘/node_modules/egg-scripts/lib/start-cluster’,即新建的进程运行的是start-cluster,而start-cluster运行了egg-cluster的startCluster()函数。
// node_modules/egg-scripts/lib/cmd/start.js * run(context) {...}
// whether run in the background.
if (isDaemon) {
this.logger.info(`Save log file to ${logDir}`);
const [ stdout, stderr ] = yield [ getRotatelog(argv.stdout), getRotatelog(argv.stderr);
options.stdio = [ 'ignore', stdout, stderr, 'ipc' ];
options.detached = true;
const child = this.child = spawn('node', eggArgs, options);
this.isReady = false;
child.on('message', msg => {
if (msg && msg.action === 'egg-ready') {
this.isReady = true;
this.logger.info('%s started on %s', this.frameworkName, msg.data.address);
child.unref();
child.disconnect();
process.exit(0);
}
});
// check start status
yield this.checkStatus(argv);
} else {