Added ability to start a server

This commit is contained in:
Gregory Ballantine 2022-10-07 16:43:04 -04:00
parent 8e80151331
commit 6776307159
6 changed files with 100 additions and 12 deletions

View File

@ -1,3 +1,4 @@
const { exec } = require("child_process");
const fs = require('fs'); const fs = require('fs');
class Server { class Server {
@ -11,21 +12,44 @@ class Server {
if (fs.existsSync(versionFilePath)) { if (fs.existsSync(versionFilePath)) {
this.version = fs.readFileSync(versionFilePath, {encoding:'utf8', flag:'r'}); this.version = fs.readFileSync(versionFilePath, {encoding:'utf8', flag:'r'});
} }
// set server state
if (fs.existsSync(this.pidFilePath)) {
this.state = true;
} else {
this.state = false;
}
} }
start() { start() {
console.log('Starting server...'); console.log(`Starting server ${this.name}...`);
// create shell command and execute it
let cmd = `${this.rootDir}/start.sh`;
exec(cmd, (err, stdout, stderr) => {
if (err) {
console.log(`Error while starting server: ${error.message}`);
}
console.log(`Server ${this.name} has been started.`);
});
} }
stop() { stop() {
console.log('Stopping server...'); console.log(`Stopping server ${this.name}...`);
}
getStatus() {
if (fs.existsSync(this.pidFilePath)) {
let pid = fs.readFileSync(this.pidFilePath, {encoding: 'utf8', flag: 'r'});
try {
return process.kill(pid, 0);
} catch (err) {
// ESRCH error means the process doesn't exist, so should return false
if (err.code !== 'ESRCH') {
console.error(err);
return err.code === 'EPERM';
} else {
// delete pid.txt so we don't have to worry about checking it again
fs.unlinkSync(this.pidFilePath);
}
}
}
return false
} }
getPid() { getPid() {

View File

@ -18,11 +18,13 @@ var serverRoutes = require('./routes/server');
app.get('/', homeRoutes.getIndex); app.get('/', homeRoutes.getIndex);
app.get('/server/create', serverRoutes.getCreate); app.get('/server/create', serverRoutes.getCreate);
app.post('/server/create', serverRoutes.postCreate); app.post('/server/create', serverRoutes.postCreate);
app.get('/server/:serverName/start', serverRoutes.getStart);
app.get('/server/:serverName/stop', serverRoutes.getStop);
// set Express to serve static files (ideally this is only used in development) // set Express to serve static files (ideally this is only used in development)
app.use(express.static('./static/')); app.use(express.static('./static/'));
// start Express.js app // start Express.js app
app.listen(port, () => { app.listen(port, () => {
console.log(`Example app listening on port ${port}`); console.log(`MCST has started and is listening on port ${port}.`);
}); });

36
package-lock.json generated
View File

@ -9,6 +9,7 @@
"version": "0.1.0", "version": "0.1.0",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"config": "^3.3.8",
"express": "^4.18.1", "express": "^4.18.1",
"pug": "^3.0.2" "pug": "^3.0.2"
} }
@ -153,6 +154,17 @@
"is-regex": "^1.0.3" "is-regex": "^1.0.3"
} }
}, },
"node_modules/config": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/config/-/config-3.3.8.tgz",
"integrity": "sha512-rFzF6VESOdp7wAXFlB9IOZI4ouL05g3A03v2eRcTHj2JBQaTNJ40zhAUl5wRbWHqLZ+uqp/7OE0BWWtAVgrong==",
"dependencies": {
"json5": "^2.2.1"
},
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/constantinople": { "node_modules/constantinople": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz",
@ -462,6 +474,17 @@
"resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
"integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
}, },
"node_modules/json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/jstransformer": { "node_modules/jstransformer": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
@ -1051,6 +1074,14 @@
"is-regex": "^1.0.3" "is-regex": "^1.0.3"
} }
}, },
"config": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/config/-/config-3.3.8.tgz",
"integrity": "sha512-rFzF6VESOdp7wAXFlB9IOZI4ouL05g3A03v2eRcTHj2JBQaTNJ40zhAUl5wRbWHqLZ+uqp/7OE0BWWtAVgrong==",
"requires": {
"json5": "^2.2.1"
}
},
"constantinople": { "constantinople": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz", "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-4.0.1.tgz",
@ -1290,6 +1321,11 @@
"resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz", "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
"integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g==" "integrity": "sha512-rtS5ATOo2Q5k1G+DADISilDA6lv79zIiwFd6CcjuIxGKLFm5C+RLImRscVap9k55i+MOZwgliw+NejvkLuGD5g=="
}, },
"json5": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
},
"jstransformer": { "jstransformer": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz", "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",

View File

@ -19,6 +19,7 @@
"author": "Gregory Ballantine <gballantine@bitgoblin.tech>", "author": "Gregory Ballantine <gballantine@bitgoblin.tech>",
"license": "BSD-2-Clause", "license": "BSD-2-Clause",
"dependencies": { "dependencies": {
"config": "^3.3.8",
"express": "^4.18.1", "express": "^4.18.1",
"pug": "^3.0.2" "pug": "^3.0.2"
} }

View File

@ -2,6 +2,7 @@ const config = require('config');
const fs = require('fs'); const fs = require('fs');
const https = require('https'); const https = require('https');
const path = require('path'); const path = require('path');
const minecraft = require('../app/MinecraftServer');
exports.getCreate = function(req, res) { exports.getCreate = function(req, res) {
// render view // render view
@ -30,7 +31,7 @@ exports.postCreate = function(req, res) {
// create the start.sh shell script // create the start.sh shell script
scriptFilePath = path.join(serverDir, 'start.sh'); scriptFilePath = path.join(serverDir, 'start.sh');
scriptContent = "#!/bin/sh\n\ncd " + serverDir + "\njava -Xmx2048M -Xms2048M -jar server_" + req.body.serverVersion + ".jar nogui"; scriptContent = "#!/bin/sh\n\ncd " + serverDir + "\njava -Xmx2048M -Xms2048M -jar server_" + req.body.serverVersion + ".jar nogui &\n\necho \"$!\" > ./pid.txt";
fs.writeFileSync(scriptFilePath, scriptContent); fs.writeFileSync(scriptFilePath, scriptContent);
fs.chmodSync(scriptFilePath, 0o755); fs.chmodSync(scriptFilePath, 0o755);
@ -43,3 +44,27 @@ exports.postCreate = function(req, res) {
// redirect the user back to the home page // redirect the user back to the home page
res.redirect('/'); res.redirect('/');
}; };
exports.getStart = function(req, res) {
let serverName = req.params.serverName;
let rootDir = config.get('server_directory');
let server = new minecraft.Server(path.join(rootDir, serverName));
// start the server
server.start();
// redirect the user back to the home page
res.redirect('/');
};
exports.getStop = function(req, res) {
let serverName = req.params.serverName;
let rootDir = config.get('server_directory');
let server = new minecraft.Server(path.join(rootDir, serverName));
// stop the server
server.stop();
// redirect the user back to the home page
res.redirect('/');
};

View File

@ -24,7 +24,7 @@ block content
tr.serverItem tr.serverItem
td.serverName= m.name td.serverName= m.name
td.serverVersion= m.version td.serverVersion= m.version
td.serverState= m.state td.serverState= m.getStatus()
td td
a(href='/server/' + m.name + '/start') Start a(href='/server/' + m.name + '/start') Start
a(href='/server/' + m.name + '/stop') Stop a(href='/server/' + m.name + '/stop') Stop