Skip to content

feat: support stop --title #16

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 28, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
2 changes: 1 addition & 1 deletion lib/cmd/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
25 changes: 14 additions & 11 deletions lib/cmd/stop.js
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand All @@ -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);

Expand All @@ -55,7 +56,9 @@ class StopCommand extends Command {
// node /Users/tz/Workspaces/eggjs/test/showcase/node_modules/[email protected]@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);

Expand Down
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,24 @@
},
"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",
"runscript": "^1.3.0",
"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": {
Expand Down
184 changes: 123 additions & 61 deletions test/stop.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -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));
});
});

Expand All @@ -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();
Expand All @@ -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'));
});
});
});