shell script runner

This commit is contained in:
Jan Prochazka
2020-06-07 09:51:53 +02:00
parent 617548cd50
commit f37524f76f
14 changed files with 203 additions and 89 deletions

View File

@@ -0,0 +1,93 @@
const _ = require('lodash');
const path = require('path');
const fs = require('fs');
const uuidv1 = require('uuid/v1');
const socket = require('../utility/socket');
const { fork } = require('child_process');
const { rundir, uploadsdir } = require('../utility/directories');
const scriptTemplate = (script) => `
const dbgateApi = require(process.env.DBGATE_API || "@dbgate/api");
require=null;
async function run() {
${script}
}
dbgateApi.runScript(run);
`;
module.exports = {
/** @type {import('@dbgate/types').OpenedRunner[]} */
opened: [],
dispatchMessage(runid, message) {
console.log('DISPATCHING', message);
if (_.isString(message)) {
socket.emit(`runner-info-${runid}`, {
message,
time: new Date(),
severity: 'info',
});
}
if (_.isPlainObject(message)) {
socket.emit(`runner-info-${runid}`, {
time: new Date(),
severity: 'info',
...message,
});
}
},
handle_ping() {},
start_meta: 'post',
async start({ script }) {
const runid = uuidv1();
const directory = path.join(rundir(), runid);
const scriptFile = path.join(uploadsdir(), runid + '.js');
fs.writeFileSync(`${scriptFile}`, scriptTemplate(script));
fs.mkdirSync(directory);
console.log(`RUNNING SCRIPT ${scriptFile}`);
const subprocess = fork(scriptFile, ['--checkParent'], {
cwd: directory,
stdio: ['ignore', 'pipe', 'pipe', 'ipc'],
env: {
DBGATE_API: process.argv[1],
},
});
subprocess.stdout.on('data', (data) => this.dispatchMessage(runid, data.toString()));
subprocess.stderr.on('data', (data) =>
data.toString.split('\n').forEach((message) => {
this.dispatchMessage(runid, { severity: 'error', message });
})
);
subprocess.on('exit', (code) => {
socket.emit(`runner-done-${runid}`, code);
});
subprocess.on('error', (error) => {
this.dispatchMessage({
severity: 'error',
message: error.toString(),
});
});
const newOpened = {
runid,
subprocess,
};
this.opened.push(newOpened);
// @ts-ignore
subprocess.on('message', ({ msgtype, ...message }) => {
this[`handle_${msgtype}`](runid, message);
});
return newOpened;
},
cancel_meta: 'post',
async cancel({ runid }) {
const session = this.opened.find((x) => x.runid == runid);
if (!session) {
throw new Error('Invalid runner');
}
session.subprocess.kill();
return { state: 'ok' };
},
};

View File

@@ -18,4 +18,4 @@ if (argument && argument.endsWith('Process')) {
main.start(argument);
}
module.exports = shell;
module.exports = shell;

View File

@@ -15,11 +15,12 @@ const serverConnections = require('./controllers/serverConnections');
const databaseConnections = require('./controllers/databaseConnections');
const metadata = require('./controllers/metadata');
const sessions = require('./controllers/sessions');
const runners = require('./controllers/runners');
const jsldata = require('./controllers/jsldata');
const config = require('./controllers/config');
function start(argument = null) {
console.log('process.argv', process.argv);
// console.log('process.argv', process.argv);
const app = express();
@@ -34,6 +35,7 @@ function start(argument = null) {
useController(app, '/database-connections', databaseConnections);
useController(app, '/metadata', metadata);
useController(app, '/sessions', sessions);
useController(app, '/runners', runners);
useController(app, '/jsldata', jsldata);
useController(app, '/config', config);

View File

@@ -1,4 +1,9 @@
const childProcessChecker = require('../utility/childProcessChecker');
async function runScript(func) {
if (process.argv.includes('--checkParent')) {
childProcessChecker();
}
try {
await func();
process.exit(0);

View File

@@ -9,7 +9,7 @@ function childProcessChecker() {
// One way can be to check for error code ERR_IPC_CHANNEL_CLOSED
// and call process.exit()
console.log('parent died', ex.toString());
process.exit();
process.exit(1);
}
}, 1000);
}

View File

@@ -3,7 +3,7 @@ const path = require('path');
const fs = require('fs');
let createdDatadir = false;
let createdJsldir = false;
const createDirectories = {};
function datadir() {
const dir = path.join(os.homedir(), 'dbgate-data');
@@ -18,20 +18,26 @@ function datadir() {
return dir;
}
function jsldir() {
const dir = path.join(datadir(), 'jsl');
if (!createdJsldir) {
const dirFunc = (dirname) => () => {
const dir = path.join(datadir(), dirname);
if (!createDirectories[dirname]) {
if (!fs.existsSync(dir)) {
console.log(`Creating jsl directory ${dir}`);
fs.mkdirSync(dir);
}
createdJsldir = true;
createDirectories[dirname] = true;
}
return dir;
}
};
const jsldir = dirFunc('jsl');
const rundir = dirFunc('run');
const uploadsdir = dirFunc('uploads');
module.exports = {
datadir,
jsldir,
rundir,
uploadsdir,
};