Skip to content

Commit b5559d5

Browse files
atian25popomore
authored andcommitted
feat: support --ignore-error (#17)
1 parent 3684d9f commit b5559d5

File tree

3 files changed

+63
-32
lines changed

3 files changed

+63
-32
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ $ eggctl start [options] [baseDir]
5454
- `stdout` - customize stdout file, default to `$HOME/logs/master-stdout.log`.
5555
- `stderr` - customize stderr file, default to `$HOME/logs/master-stderr.log`.
5656
- `timeout` - the maximum timeout when app starts, default to 300s.
57+
- `ignore-stderr` - whether ignore stderr when app starts.
5758

5859
### stop
5960

lib/cmd/start.js

Lines changed: 47 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ class StartCommand extends Command {
5959
type: 'number',
6060
default: 300 * 1000,
6161
},
62+
'ignore-stderr': {
63+
description: 'whether ignore stderr when app starts',
64+
type: 'boolean',
65+
},
6266
};
6367
}
6468

@@ -67,15 +71,16 @@ class StartCommand extends Command {
6771
}
6872

6973
* run(context) {
70-
const argv = Object.assign({}, context.argv);
74+
const { argv, env, cwd, execArgv } = context;
75+
7176
const HOME = homedir();
7277
const logDir = path.join(HOME, 'logs');
7378

7479
// egg-script start
7580
// egg-script start ./server
7681
// egg-script start /opt/app
77-
let baseDir = argv._[0] || context.cwd;
78-
if (!path.isAbsolute(baseDir)) baseDir = path.join(context.cwd, baseDir);
82+
let baseDir = argv._[0] || cwd;
83+
if (!path.isAbsolute(baseDir)) baseDir = path.join(cwd, baseDir);
7984
argv.baseDir = baseDir;
8085

8186
const isDaemon = argv.daemon;
@@ -93,24 +98,18 @@ class StartCommand extends Command {
9398
argv.stdout = argv.stdout || path.join(logDir, 'master-stdout.log');
9499
argv.stderr = argv.stderr || path.join(logDir, 'master-stderr.log');
95100

96-
const env = context.env;
101+
// normalize env
97102
env.HOME = HOME;
98103
env.NODE_ENV = 'production';
99104

100-
// adjust env for win
101-
const currentPATH = env.PATH || env.Path;
102-
// for nodeinstall
103-
let newPATH = `${path.join(baseDir, 'node_modules/.bin')}${path.delimiter}`;
104-
// support `${baseDir}/.node/bin`
105-
const customNodeBinDir = path.join(baseDir, '.node/bin');
106-
if (yield fs.exists(customNodeBinDir)) {
107-
newPATH += `${customNodeBinDir}${path.delimiter}`;
108-
}
109-
if (currentPATH) {
110-
env.PATH = `${newPATH}${currentPATH}`;
111-
} else {
112-
env.PATH = newPATH;
113-
}
105+
env.PATH = [
106+
// for nodeinstall
107+
path.join(baseDir, 'node_modules/.bin'),
108+
// support `.node/bin`, due to npm5 will remove `node_modules/.bin`
109+
path.join(baseDir, '.node/bin'),
110+
// adjust env for win
111+
env.PATH || env.Path,
112+
].filter(x => !!x).join(path.delimiter);
114113

115114
// for alinode
116115
env.ENABLE_NODE_LOG = 'YES';
@@ -121,24 +120,20 @@ class StartCommand extends Command {
121120
if (argv.env) {
122121
// if undefined, should not pass key due to `spwan`, https://github.com/nodejs/node/blob/master/lib/child_process.js#L470
123122
env.EGG_SERVER_ENV = argv.env;
124-
argv.env = undefined;
125123
}
126124

127-
// remove unused properties, alias had been remove by `removeAlias`
128-
argv._ = undefined;
129-
argv.$0 = undefined;
130-
argv.daemon = undefined;
131-
132125
const options = {
133-
execArgv: context.execArgv,
126+
execArgv,
134127
env,
135128
stdio: 'inherit',
136129
detached: false,
137130
};
138131

139132
this.logger.info('Starting %s application at %s', this.frameworkName, baseDir);
140133

141-
const eggArgs = [ this.serverBin, JSON.stringify(argv), `--title=${argv.title}` ];
134+
// remove unused properties from stringify, alias had been remove by `removeAlias`
135+
const ignoreKeys = [ '_', '$0', 'env', 'daemon', 'stdout', 'stderr', 'timeout', 'ignore-stderr' ];
136+
const eggArgs = [ this.serverBin, stringify(argv, ignoreKeys), `--title=${argv.title}` ];
142137
this.logger.info('Run node %s', eggArgs.join(' '));
143138

144139
// whether run in the background.
@@ -151,6 +146,7 @@ class StartCommand extends Command {
151146
const child = this.child = spawn('node', eggArgs, options);
152147
this.isReady = false;
153148
child.on('message', msg => {
149+
/* istanbul ignore else */
154150
if (msg && msg.action === 'egg-ready') {
155151
this.isReady = true;
156152
this.logger.info('%s started on %s', this.frameworkName, msg.data.address);
@@ -177,25 +173,24 @@ class StartCommand extends Command {
177173
let name = 'egg';
178174
try {
179175
const pkg = require(pkgPath);
176+
/* istanbul ignore else */
180177
if (pkg.name) name = pkg.name;
181178
} catch (_) {
182179
/* istanbul next */
183180
}
184181
return name;
185182
}
186183

187-
* checkStatus({ stderr, timeout }) {
184+
* checkStatus({ stderr, timeout, 'ignore-stderr': ignoreStdErr }) {
188185
let count = 0;
186+
let hasError = false;
189187
let isSuccess = true;
190188
timeout = timeout / 1000;
191189
while (!this.isReady) {
192190
try {
193191
const stat = yield fs.stat(stderr);
194192
if (stat && stat.size > 0) {
195-
const [ stdout ] = yield exec('tail -n 100 ' + stderr);
196-
this.logger.error(stdout);
197-
this.logger.error('Start failed, see %s', stderr);
198-
isSuccess = false;
193+
hasError = true;
199194
break;
200195
}
201196
} catch (_) {
@@ -212,6 +207,17 @@ class StartCommand extends Command {
212207
this.logger.log('Wait Start: %d...', ++count);
213208
}
214209

210+
if (hasError) {
211+
try {
212+
const [ stdout ] = yield exec('tail -n 100 ' + stderr);
213+
this.logger.error(stdout);
214+
} catch (_) {
215+
// nothing
216+
}
217+
isSuccess = ignoreStdErr;
218+
this.logger.error('Start got error, see %s', stderr);
219+
}
220+
215221
if (!isSuccess) {
216222
this.child.kill('SIGTERM');
217223
yield sleep(1000);
@@ -233,4 +239,14 @@ function* getRotatelog(logfile) {
233239
return yield fs.open(logfile, 'a');
234240
}
235241

242+
function stringify(obj, ignore) {
243+
const result = {};
244+
Object.keys(obj).forEach(key => {
245+
if (!ignore.includes(key)) {
246+
result[key] = obj[key];
247+
}
248+
});
249+
return JSON.stringify(result);
250+
}
251+
236252
module.exports = StartCommand;

test/start.test.js

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -468,6 +468,20 @@ describe('test/start.test.js', () => {
468468
.end();
469469
});
470470

471+
it('should status check fail `--ignore-stderr`, exit with 0', function* () {
472+
mm(process.env, 'WAIT_TIME', 5000);
473+
mm(process.env, 'ERROR', 'error message');
474+
475+
const stderr = path.join(homePath, 'logs/master-stderr.log');
476+
477+
yield coffee.fork(eggBin, [ 'start', '--daemon', '--workers=1', '--ignore-stderr' ], { cwd })
478+
// .debug()
479+
.expect('stderr', /nodejs.Error: error message/)
480+
.expect('stderr', new RegExp(`Start got error, see ${stderr}`))
481+
.expect('code', 0)
482+
.end();
483+
});
484+
471485
it('should status check fail, exit with 1', function* () {
472486
mm(process.env, 'WAIT_TIME', 5000);
473487
mm(process.env, 'ERROR', 'error message');
@@ -477,7 +491,7 @@ describe('test/start.test.js', () => {
477491
yield coffee.fork(eggBin, [ 'start', '--daemon', '--workers=1' ], { cwd })
478492
// .debug()
479493
.expect('stderr', /nodejs.Error: error message/)
480-
.expect('stderr', new RegExp(`Start failed, see ${stderr}`))
494+
.expect('stderr', new RegExp(`Start got error, see ${stderr}`))
481495
.expect('code', 1)
482496
.end();
483497
});

0 commit comments

Comments
 (0)