diff --git a/config.json b/config.json index f6bf160..c8d9b5c 100644 --- a/config.json +++ b/config.json @@ -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": [] } ] } \ No newline at end of file diff --git a/libs/commands.js b/libs/commands.js index 7fe85e2..bb5b19f 100644 --- a/libs/commands.js +++ b/libs/commands.js @@ -1,5 +1,5 @@ const logger = require('./logger.js'); -const { spawn } = require('child_process') +const { spawn } = require('child_process'); const cmds = new Map(); @@ -7,9 +7,13 @@ 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'); - throw new Error('command 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 + '\')...'); @@ -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 = { diff --git a/libs/server.js b/libs/server.js index 9b52d67..dbf5713 100644 --- a/libs/server.js +++ b/libs/server.js @@ -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);