diff --git a/README.md b/README.md index ce7c284..1b7e96a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ $ eggctl start [options] [baseDir] - `baseDir` - directory of application, default to `process.cwd()`. - **Options** - `port` - listening port, default to `process.env.PORT`, if unset, egg will use `7001` as default. - - `title` - process title description, use for kill grep, default to `egg-server-APPNAME`. + - `title` - process title description, use for kill grep, default to `egg-server-${APP_NAME}`. - `workers` - numbers of app workers, default to `process.env.EGG_WORKERS`, if unset, egg will use `os.cpus().length` as default. - `daemon` - whether run at background daemon mode. - `framework` - specify framework that can be absolute path or npm package, default to auto detect. @@ -61,9 +61,8 @@ Stop egg gracefull. ```bash # stop egg -$ eggctl stop [baseDir] -# eggctl stop ./server +$ eggctl stop [--title=example] ``` -- **Arguments** - - `baseDir` - directory of application, default to `process.cwd()`. +- **Options** + - `title` - process title description, use for kill grep. \ No newline at end of file diff --git a/lib/cmd/start.js b/lib/cmd/start.js index 53361bc..09fbd50 100644 --- a/lib/cmd/start.js +++ b/lib/cmd/start.js @@ -19,7 +19,7 @@ class StartCommand extends Command { this.options = { title: { - description: 'process title description, use for kill grep, default to `egg-server-APPNAME`', + description: 'process title description, use for kill grep, default to `egg-server-${APP_NAME}`', type: 'string', }, workers: { diff --git a/lib/cmd/stop.js b/lib/cmd/stop.js index ec5fb56..09585c8 100644 --- a/lib/cmd/stop.js +++ b/lib/cmd/stop.js @@ -8,8 +8,14 @@ class StopCommand extends Command { constructor(rawArgv) { super(rawArgv); - this.usage = 'Usage: egg-scripts stop [baseDir]'; + this.usage = 'Usage: egg-scripts stop [--title=example]'; this.serverBin = path.join(__dirname, '../start-cluster'); + this.options = { + title: { + description: 'process title description, use for kill grep', + type: 'string', + }, + }; } get description() { @@ -25,19 +31,14 @@ class StopCommand extends Command { const { argv } = context; - // egg-script stop - // egg-script stop ./server - // egg-script stop /opt/app - let baseDir = argv._[0] || context.cwd; - if (!path.isAbsolute(baseDir)) baseDir = path.join(context.cwd, baseDir); - argv.baseDir = baseDir; - - this.logger.info(`stopping egg application at ${baseDir}`); + this.logger.info(`stopping egg application ${argv.title ? `with --title=${argv.title}` : ''}`); // node /Users/tz/Workspaces/eggjs/egg-scripts/lib/start-cluster {"title":"egg-server","workers":4,"port":7001,"baseDir":"/Users/tz/Workspaces/eggjs/test/showcase","framework":"/Users/tz/Workspaces/eggjs/test/showcase/node_modules/egg"} let processList = yield this.helper.findNodeProcess(item => { const cmd = item.cmd; - return cmd.includes('start-cluster'); + return argv.title ? + cmd.includes('start-cluster') && cmd.includes(`"title":"${argv.title}"`) : + cmd.includes('start-cluster'); }); let pids = processList.map(x => x.pid); @@ -55,7 +56,9 @@ class StopCommand extends Command { // node /Users/tz/Workspaces/eggjs/test/showcase/node_modules/_egg-cluster@1.8.0@egg-cluster/lib/app_worker.js {"framework":"/Users/tz/Workspaces/eggjs/test/showcase/node_modules/egg","baseDir":"/Users/tz/Workspaces/eggjs/test/showcase","port":7001,"workers":2,"plugins":null,"https":false,"key":"","cert":"","title":"egg-server","clusterPort":52406} processList = yield this.helper.findNodeProcess(item => { const cmd = item.cmd; - return cmd.includes('egg-cluster/lib/app_worker.js') || cmd.includes('egg-cluster/lib/agent_worker.js'); + return argv.title ? + (cmd.includes('egg-cluster/lib/app_worker.js') || cmd.includes('egg-cluster/lib/agent_worker.js')) && cmd.includes(`"title":"${argv.title}"`) : + (cmd.includes('egg-cluster/lib/app_worker.js') || cmd.includes('egg-cluster/lib/agent_worker.js')); }); pids = processList.map(x => x.pid); diff --git a/package.json b/package.json index 294a525..fe17c02 100644 --- a/package.json +++ b/package.json @@ -9,8 +9,8 @@ }, "dependencies": { "common-bin": "^2.7.1", - "egg-utils": "^2.2.0", - "moment": "^2.19.1", + "egg-utils": "^2.3.0", + "moment": "^2.19.2", "mz": "^2.7.0", "mz-modules": "^2.0.0", "node-homedir": "^1.1.0", @@ -18,15 +18,15 @@ "zlogger": "^1.1.0" }, "devDependencies": { - "autod": "^2.10.1", + "autod": "^3.0.1", "coffee": "^4.1.0", - "egg": "^1.9.0", + "egg": "^1.11.0", "egg-bin": "^4.3.5", "egg-ci": "^1.8.0", - "eslint": "^4.8.0", + "eslint": "^4.11.0", "eslint-config-egg": "^5.1.1", "mm": "^2.2.0", - "urllib": "^2.25.0", + "urllib": "^2.25.1", "webstorm-disable-index": "^1.2.0" }, "engines": { diff --git a/test/stop.test.js b/test/stop.test.js index bb79773..d623700 100644 --- a/test/stop.test.js +++ b/test/stop.test.js @@ -49,67 +49,23 @@ describe('test/stop.test.js', () => { yield utils.cleanup(fixturePath); }); - describe('full path', () => { - it('should stop', function* () { - killer = coffee.fork(eggBin, [ 'stop', fixturePath ]); - killer.debug(); - killer.expect('code', 0); - - // yield killer.end(); - yield sleep(waitTime); - - // make sure is kill not auto exist - assert(!app.stdout.includes('exist by env')); - - assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); - assert(app.stdout.includes('[master] exit with code:0')); - assert(app.stdout.includes('[app_worker] exit with code:0')); - // assert(app.stdout.includes('[agent_worker] exit with code:0')); - assert(killer.stdout.includes(`[egg-scripts] stopping egg application at ${fixturePath}`)); - assert(killer.stdout.match(/got master pid \["\d+\"\]/i)); - }); - }); + it('should stop', function* () { + killer = coffee.fork(eggBin, [ 'stop', fixturePath ]); + killer.debug(); + killer.expect('code', 0); - describe('relative path', () => { - it('should stop', function* () { - killer = coffee.fork(eggBin, [ 'stop', path.relative(process.cwd(), fixturePath) ]); - killer.debug(); - killer.expect('code', 0); - - // yield killer.end(); - yield sleep(waitTime); - - // make sure is kill not auto exist - assert(!app.stdout.includes('exist by env')); - - assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); - assert(app.stdout.includes('[master] exit with code:0')); - assert(app.stdout.includes('[app_worker] exit with code:0')); - // assert(app.stdout.includes('[agent_worker] exit with code:0')); - assert(killer.stdout.includes(`[egg-scripts] stopping egg application at ${fixturePath}`)); - assert(killer.stdout.match(/got master pid \["\d+\"\]/i)); - }); - }); + // yield killer.end(); + yield sleep(waitTime); + + // make sure is kill not auto exist + assert(!app.stdout.includes('exist by env')); - describe('without baseDir', () => { - it('should stop', function* () { - killer = coffee.fork(eggBin, [ 'stop' ], { cwd: fixturePath }); - killer.debug(); - killer.expect('code', 0); - - // yield killer.end(); - yield sleep(waitTime); - - // make sure is kill not auto exist - assert(!app.stdout.includes('exist by env')); - - assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); - assert(app.stdout.includes('[master] exit with code:0')); - assert(app.stdout.includes('[app_worker] exit with code:0')); - // assert(app.stdout.includes('[agent_worker] exit with code:0')); - assert(killer.stdout.includes(`[egg-scripts] stopping egg application at ${fixturePath}`)); - assert(killer.stdout.match(/got master pid \["\d+\"\]/i)); - }); + assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); + assert(app.stdout.includes('[master] exit with code:0')); + assert(app.stdout.includes('[app_worker] exit with code:0')); + // assert(app.stdout.includes('[agent_worker] exit with code:0')); + assert(killer.stdout.includes('[egg-scripts] stopping egg application')); + assert(killer.stdout.match(/got master pid \["\d+\"\]/i)); }); }); @@ -132,7 +88,7 @@ describe('test/stop.test.js', () => { it('should stop', function* () { yield coffee.fork(eggBin, [ 'stop', fixturePath ]) .debug() - .expect('stdout', new RegExp(`\\[egg-scripts] stopping egg application at ${fixturePath}`)) + .expect('stdout', /\[egg-scripts] stopping egg application/) .expect('stdout', /got master pid \["\d+\"\]/i) .expect('code', 0) .end(); @@ -159,10 +115,116 @@ describe('test/stop.test.js', () => { yield utils.cleanup(fixturePath); yield coffee.fork(eggBin, [ 'stop', fixturePath ]) .debug() - .expect('stdout', new RegExp(`\\[egg-scripts] stopping egg application at ${fixturePath}`)) + .expect('stdout', /\[egg-scripts] stopping egg application/) + .expect('stderr', /can't detect any running egg process/) + .expect('code', 0) + .end(); + }); + }); + + describe('stop --title', () => { + let app; + let killer; + + beforeEach(function* () { + yield utils.cleanup(fixturePath); + app = coffee.fork(eggBin, [ 'start', '--workers=2', '--title=example', fixturePath ]); + // app.debug(); + app.expect('code', 0); + yield sleep(waitTime); + + assert(app.stderr === ''); + assert(app.stdout.match(/custom-framework started on http:\/\/127\.0\.0\.1:7001/)); + const result = yield httpclient.request('http://127.0.0.1:7001'); + assert(result.data.toString() === 'hi, egg'); + }); + + afterEach(function* () { + app.proc.kill('SIGTERM'); + yield utils.cleanup(fixturePath); + }); + + it('should stop', function* () { + yield coffee.fork(eggBin, [ 'stop', '--title=random', fixturePath ]) + .debug() + .expect('stdout', /\[egg-scripts] stopping egg application with --title=random/) .expect('stderr', /can't detect any running egg process/) .expect('code', 0) .end(); + + killer = coffee.fork(eggBin, [ 'stop', '--title=example' ], { cwd: fixturePath }); + killer.debug(); + killer.expect('code', 0); + + // yield killer.end(); + yield sleep(waitTime); + + // make sure is kill not auto exist + assert(!app.stdout.includes('exist by env')); + + assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); + assert(app.stdout.includes('[master] exit with code:0')); + assert(app.stdout.includes('[app_worker] exit with code:0')); + // assert(app.stdout.includes('[agent_worker] exit with code:0')); + assert(killer.stdout.includes('[egg-scripts] stopping egg application with --title=example')); + assert(killer.stdout.match(/got master pid \["\d+\"\]/i)); + }); + }); + + describe('stop all', () => { + let app; + let app2; + let killer; + + beforeEach(function* () { + yield utils.cleanup(fixturePath); + app = coffee.fork(eggBin, [ 'start', '--workers=2', '--title=example', fixturePath ]); + // app.debug(); + app.expect('code', 0); + + app2 = coffee.fork(eggBin, [ 'start', '--workers=2', '--title=test', '--port=7002', fixturePath ]); + app2.expect('code', 0); + + yield sleep(waitTime); + + assert(app.stderr === ''); + assert(app.stdout.match(/custom-framework started on http:\/\/127\.0\.0\.1:7001/)); + const result = yield httpclient.request('http://127.0.0.1:7001'); + assert(result.data.toString() === 'hi, egg'); + + assert(app2.stderr === ''); + assert(app2.stdout.match(/custom-framework started on http:\/\/127\.0\.0\.1:7002/)); + const result2 = yield httpclient.request('http://127.0.0.1:7002'); + assert(result2.data.toString() === 'hi, egg'); + }); + + afterEach(function* () { + app.proc.kill('SIGTERM'); + app2.proc.kill('SIGTERM'); + yield utils.cleanup(fixturePath); + }); + + it('should stop', function* () { + killer = coffee.fork(eggBin, [ 'stop' ], { cwd: fixturePath }); + killer.debug(); + killer.expect('code', 0); + + // yield killer.end(); + yield sleep(waitTime); + + // make sure is kill not auto exist + assert(!app.stdout.includes('exist by env')); + assert(app.stdout.includes('[master] receive signal SIGTERM, closing')); + assert(app.stdout.includes('[master] exit with code:0')); + assert(app.stdout.includes('[app_worker] exit with code:0')); + // assert(app.stdout.includes('[agent_worker] exit with code:0')); + assert(killer.stdout.includes('[egg-scripts] stopping egg application')); + assert(killer.stdout.match(/got master pid \["\d+\","\d+\"\]/i)); + + assert(!app2.stdout.includes('exist by env')); + assert(app2.stdout.includes('[master] receive signal SIGTERM, closing')); + assert(app2.stdout.includes('[master] exit with code:0')); + assert(app2.stdout.includes('[app_worker] exit with code:0')); }); }); });