22
33const path = require ( 'path' ) ;
44const mkdirp = require ( 'mz-modules/mkdirp' ) ;
5+ const sleep = require ( 'mz-modules/sleep' ) ;
56const homedir = require ( 'node-homedir' ) ;
67const utils = require ( 'egg-utils' ) ;
78const fs = require ( 'mz/fs' ) ;
9+ const { exec } = require ( 'mz/child_process' ) ;
810const moment = require ( 'moment' ) ;
911const spawn = require ( 'child_process' ) . spawn ;
1012const Command = require ( '../command' ) ;
@@ -33,7 +35,7 @@ class StartCommand extends Command {
3335 default : process . env . PORT ,
3436 } ,
3537 env : {
36- description : 'egg server env, default to `process.env.EGG_SERVER_ENV`' ,
38+ description : 'server env, default to `process.env.EGG_SERVER_ENV`' ,
3739 default : process . env . EGG_SERVER_ENV ,
3840 } ,
3941 framework : {
@@ -52,6 +54,11 @@ class StartCommand extends Command {
5254 description : 'A file that stderr redirect to' ,
5355 type : 'string' ,
5456 } ,
57+ timeout : {
58+ description : 'a timeout for start when daemon' ,
59+ type : 'number' ,
60+ default : 300 * 1000 ,
61+ } ,
5562 } ;
5663 }
5764
@@ -78,6 +85,8 @@ class StartCommand extends Command {
7885 baseDir,
7986 } ) ;
8087
88+ this . frameworkName = yield this . getFrameworkName ( argv . framework ) ;
89+
8190 const pkgInfo = require ( path . join ( baseDir , 'package.json' ) ) ;
8291 argv . title = argv . title || `egg-server-${ pkgInfo . name } ` ;
8392
@@ -120,27 +129,32 @@ class StartCommand extends Command {
120129 detached : false ,
121130 } ;
122131
123- this . logger . info ( `starting egg application at ${ baseDir } ` ) ;
132+ this . logger . info ( 'Starting %s application at %s' , this . frameworkName , baseDir ) ;
124133
125134 const eggArgs = [ this . serverBin , JSON . stringify ( argv ) , `--title=${ argv . title } ` ] ;
126- this . logger . info ( 'run node %s' , eggArgs . join ( ' ' ) ) ;
135+ this . logger . info ( 'Run node %s' , eggArgs . join ( ' ' ) ) ;
127136
128137 // whether run in the background.
129138 if ( isDaemon ) {
130- this . logger . info ( `save log file to ${ logDir } ` ) ;
139+ this . logger . info ( `Save log file to ${ logDir } ` ) ;
131140 const [ stdout , stderr ] = yield [ getRotatelog ( argv . stdout ) , getRotatelog ( argv . stderr ) ] ;
132141 options . stdio = [ 'ignore' , stdout , stderr , 'ipc' ] ;
133142 options . detached = true ;
134143
135144 const child = this . child = spawn ( 'node' , eggArgs , options ) ;
145+ this . isReady = false ;
136146 child . on ( 'message' , msg => {
137147 if ( msg && msg . action === 'egg-ready' ) {
138- this . logger . info ( `egg started on ${ msg . data . address } ` ) ;
148+ this . isReady = true ;
149+ this . logger . info ( '%s started on %s' , this . frameworkName , msg . data . address ) ;
139150 child . unref ( ) ;
140151 child . disconnect ( ) ;
141152 process . exit ( 0 ) ;
142153 }
143154 } ) ;
155+
156+ // check start status
157+ yield this . checkStatus ( argv ) ;
144158 } else {
145159 // signal event had been handler at common-bin helper
146160 this . helper . spawn ( 'node' , eggArgs , options ) ;
@@ -151,6 +165,52 @@ class StartCommand extends Command {
151165 return utils . getFrameworkPath ( params ) ;
152166 }
153167
168+ * getFrameworkName ( framework ) {
169+ const pkgPath = path . join ( framework , 'package.json' ) ;
170+ let name = 'egg' ;
171+ try {
172+ const pkg = require ( pkgPath ) ;
173+ if ( pkg . name ) name = pkg . name ;
174+ } catch ( _ ) {
175+ /* istanbul next */
176+ }
177+ return name ;
178+ }
179+
180+ * checkStatus ( { stderr, timeout } ) {
181+ let count = 0 ;
182+ let isSuccess = true ;
183+ timeout = timeout / 1000 ;
184+ while ( ! this . isReady ) {
185+ try {
186+ const stat = yield fs . stat ( stderr ) ;
187+ if ( stat && stat . size > 0 ) {
188+ const [ stdout ] = yield exec ( 'tail -n 100 ' + stderr ) ;
189+ this . logger . error ( stdout ) ;
190+ this . logger . error ( 'Start failed, see %s' , stderr ) ;
191+ isSuccess = false ;
192+ break ;
193+ }
194+ } catch ( _ ) {
195+ // nothing
196+ }
197+
198+ if ( count >= timeout ) {
199+ this . logger . error ( 'Start failed, %ds timeout' , timeout ) ;
200+ isSuccess = false ;
201+ break ;
202+ }
203+
204+ yield sleep ( 1000 ) ;
205+ this . logger . log ( 'Wait Start: %d...' , ++ count ) ;
206+ }
207+
208+ if ( ! isSuccess ) {
209+ this . child . kill ( 'SIGTERM' ) ;
210+ yield sleep ( 1000 ) ;
211+ process . exit ( 1 ) ;
212+ }
213+ }
154214}
155215
156216function * getRotatelog ( logfile ) {
0 commit comments