diff --git a/.vscode/launch.json b/.vscode/launch.json index 65f5196..9e124d0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,13 +1,11 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { "type": "pwa-node", + "runtimeVersion": "16", "request": "launch", - "name": "Launch Program", + "name": "remex", "skipFiles": [ "/**" ], diff --git a/config.json b/config.json index 896adf9..c8e9838 100644 --- a/config.json +++ b/config.json @@ -8,14 +8,21 @@ "timestamp": "DD.MM.YYYY HH:mm:ss:SS" }, "api": [ + { + "url": "/tail", + "type": "get", + "command": "tail", + "args": [ + "-f", "/tmp/test" + ], + "detach": true + }, { "url": "/uptime", "type": "get", - "command": "uptime1", + "command": "uptime", "args": [ - ], - "passargs": true, - "detach": false + ] } ] } \ No newline at end of file diff --git a/libs/commands.js b/libs/commands.js index 7889214..7fe85e2 100644 --- a/libs/commands.js +++ b/libs/commands.js @@ -7,6 +7,10 @@ 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'); + } return new Promise((resolve, reject) => { logger.info('executing command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\')...'); var cmd = spawn(endpoint.command, endpoint.args); @@ -22,14 +26,14 @@ async function execute(endpoint) { cmd.on('spawn', () => { logger.info('spawned command \'' + endpoint.command + '\' (args: \'' + endpoint.args + '\')'); addCommand(cmd, endpoint); - if (endpoint.detach !== false) { + if (endpoint.detach === true) { resolve(); } }); cmd.on('error', (err) => { error += err; removeCommand(endpoint); - if (endpoint.detach !== false) { + if (endpoint.detach === true) { reject(); } }); @@ -38,12 +42,14 @@ async function execute(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'; if (error !== undefined && error.length > 0) { - msg += ' >>> ' + error; + error = error.trim(); + msg += ' > error: ' + error; fn = logger.error; reject(error); } if (result !== undefined && result.length > 0) { - msg += ' > ' + result; + result = result.trim(); + msg += ' > data: ' + result; } fn(msg); resolve(result); diff --git a/libs/logger.js b/libs/logger.js index bfb436b..55bdc7d 100644 --- a/libs/logger.js +++ b/libs/logger.js @@ -113,11 +113,7 @@ function error(message) { } return; } - if (message.message) { - trace(message.message, 'error'); - return; - } - trace(message, 'error'); + trace(message.toString(), 'error'); } // default logging function diff --git a/libs/server.js b/libs/server.js index 9365466..8e9565a 100644 --- a/libs/server.js +++ b/libs/server.js @@ -1,7 +1,6 @@ -const logger = require('../libs/logger.js'); -const commands = require('../libs/commands.js'); +const logger = require('./logger.js'); +const commands = require('./commands.js'); const http = require('http'); -const { time } = require('console'); let server; let api; @@ -9,7 +8,7 @@ let api; async function start() { const listen = global.config?.server?.listen || '0.0.0.0'; const port = global.config?.server?.port; - buildAPI(); + setupAPI(); if (server === undefined) { server = http.createServer(); } @@ -35,8 +34,13 @@ async function respond(request, response, endpoint) { return; } let data = { - status: 'ok' + status: 'ok', + command: endpoint.command, + args: endpoint.args }; + if (endpoint.detached === true) { + data.detached = true; + } let code = 200; if (endpoint === undefined) { code = 501; @@ -48,20 +52,24 @@ async function respond(request, response, endpoint) { data.msg = 'endpoint does not support ' + request.method + ' requests'; } else { try { - data.result = await commands.execute(endpoint); + const result = await commands.execute(endpoint); + if (result !== undefined) { + data.result = result; + } } catch (err) { code = 501; data.status = 'error'; - data.msg = err; + data.msg = err.toString(); } } + data.time = new Date().getTime() - request.timestamp + 'ms'; const json = JSON.stringify(data); response.writeHead(code); response.end(json); - logger.http({ request: request, code: code, data: data }); + logger.http({ request: request, code: code, data: json }); } -function buildAPI() { +function setupAPI() { const apiConfig = global.config?.api; if (apiConfig === undefined || apiConfig.length === 0) { throw new Error('no api endpoints configured - aborting'); diff --git a/package.json b/package.json index 19f692f..8128570 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,6 @@ "description": "execute local commands remotely via http requests", "main": "remex.js", "scripts": { - "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ "scripts",