implemented kill/restart functionality

This commit is contained in:
Daniel Sommer 2022-03-18 13:56:19 +01:00
parent 739c52fc84
commit daeb9d004e
3 changed files with 39 additions and 19 deletions

View file

@ -13,16 +13,20 @@
"method": "get",
"command": "tail",
"args": [
"-f", "/tmp/test"
"-f",
"/tmp/test"
],
"detach": true
"options": {
"detach": true,
"unique": true,
"restart": true
}
},
{
"url": "/uptime",
"method": "get",
"command": "uptime",
"args": [
]
"args": []
}
]
}

View file

@ -1,5 +1,5 @@
const logger = require('./logger.js');
const { spawn } = require('child_process')
const { spawn } = require('child_process');
const cmds = new Map();
@ -7,10 +7,14 @@ async function execute(endpoint) {
if (endpoint === undefined) {
return;
}
if (isCommandActive(endpoint)) {
logger.info('not executing command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\') because it is already active');
if (endpoint.options?.unique && isCommandActive(endpoint)) {
if (!endpoint.options?.restart) {
logger.info('not executing unique command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\') because it is already active');
throw new Error('command is already active');
}
logger.info('killing and restarting unique command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\')');
await killCommand(endpoint);
}
return new Promise((resolve, reject) => {
logger.info('executing command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\')...');
var cmd = spawn(endpoint.command, endpoint.args);
@ -26,18 +30,21 @@ async function execute(endpoint) {
cmd.on('spawn', () => {
logger.info('spawned command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\')');
addCommand(cmd, endpoint);
if (endpoint.detach === true) {
if (endpoint.options?.detach) {
resolve();
}
});
cmd.on('error', (err) => {
error += err;
removeCommand(endpoint);
if (endpoint.detach === true) {
if (endpoint.options?.detach) {
reject();
}
});
cmd.on('close', (code) => {
cmd.on('exit', (code) => {
if (code === null) {
code = 0;
}
removeCommand(endpoint);
let fn = logger.info;
let msg = 'command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\') finished with exit code ' + code + ' after ' + (new Date().getTime() - cmd.timestamp) + 'ms';
@ -61,29 +68,38 @@ function addCommand(command, endpoint) {
if (command === undefined || endpoint === undefined) {
return;
}
cmds.set(JSON.stringify(endpoint), command);
cmds.set(endpoint, command);
}
function removeCommand(endpoint) {
if (endpoint === undefined) {
return;
}
cmds.delete(JSON.stringify(endpoint));
cmds.delete(endpoint);
}
function isCommandActive(endpoint) {
return endpoint !== undefined && cmds.has(JSON.stringify(endpoint));
return endpoint !== undefined && cmds.has(endpoint);
}
function killCommand(endpoint) {
async function killCommand(endpoint) {
if (endpoint === undefined) {
return;
}
const command = cmds.get(JSON.stringify(endpoint));
const command = cmds.get(endpoint);
if (command === undefined) {
return;
}
process.kill(command.pid);
process.kill(command.pid, 'SIGINT');
while(isCommandActive(endpoint)) {
await sleep(100);
}
}
async function sleep(milliseconds) {
return new Promise((resolve, reject) => {
setTimeout(resolve, milliseconds);
});
}
module.exports = {

View file

@ -1,7 +1,6 @@
const logger = require('./logger.js');
const commands = require('./commands.js');
const http = require('http');
const { config } = require('process');
let server;
let api;
@ -51,6 +50,7 @@ function finishRequest(request, response, data, code) {
if (response === undefined) {
return;
}
data.time = (new Date().getTime() - request.timestamp) + 'ms';
if (code === undefined) {
code = 200;
}
@ -59,7 +59,7 @@ function finishRequest(request, response, data, code) {
} else {
data.status = 'error';
}
data.time = (new Date().getTime() - request.timestamp) + 'ms';
response.writeHead(code);
const json = JSON.stringify(data);
response.end(json);