UNPKG

prisme-flow

Version:

prisme platform flow engine

110 lines (97 loc) 3.86 kB
/** * Created by prisme.io on 09/06/2017. */ module.exports = function (RED) { 'use strict' var spawn = require('child_process').spawn function DaemonNode (n) { RED.nodes.createNode(this, n) this.cmd = n.command this.args = n.args.trim().split(' ') || [] this.cr = n.cr this.op = n.op this.redo = n.redo this.running = false var node = this function inputlistener (msg) { if (msg != null) { if (msg.hasOwnProperty('kill') && node.running) { if (typeof msg.kill !== 'string' || msg.kill.length === 0 || !msg.kill.toUpperCase().startsWith('SIG')) { msg.kill = 'SIGINT' } node.child.kill(msg.kill.toUpperCase()) } else if (msg.hasOwnProperty('start') && !node.running) { runit() } else { if (!Buffer.isBuffer(msg.payload)) { if (typeof msg.payload === 'object') { msg.payload = JSON.stringify(msg.payload) } if (typeof msg.payload !== 'string') { msg.payload = msg.payload.toString() } if (node.cr === true) { msg.payload += '\n' } } if (RED.settings.verbose) { node.log('inp: ' + msg.payload) } if (node.child !== null && node.running) { node.child.stdin.write(msg.payload) } else { node.warn('Command not running') } } } } function runit () { node.child = spawn(node.cmd, node.args) if (RED.settings.verbose) { node.log(node.cmd + ' ' + JSON.stringify(node.args)) } node.status({fill: 'green', shape: 'dot', text: 'running'}) node.running = true var line = '' node.on('input', inputlistener) node.child.stdout.on('data', function (data) { if (node.op === 'string') { data = data.toString() } if (node.op === 'number') { data = Number(data) } if (RED.settings.verbose) { node.log('out: ' + data) } if (node.op === 'lines') { line += data.toString() var bits = line.split('\n') while (bits.length > 1) { node.send([{payload: bits.shift()}, null, null]) } line = bits[0] } else { if (data && (data.length !== 0)) { node.send([{payload: data}, null, null]) } } }) node.child.stderr.on('data', function (data) { if (node.op === 'string') { data = data.toString() } if (node.op === 'number') { data = Number(data) } if (RED.settings.verbose) { node.log('err: ' + data) } node.send([null, {payload: data}, null]) }) node.child.on('close', function (code, signal) { if (RED.settings.verbose) { node.log('ret: ' + code + ':' + signal) } node.running = false node.child = null var rc = code if (code === null) { rc = signal } node.send([null, null, {payload: rc}]) node.status({fill: 'red', shape: 'ring', text: 'stopped'}) }) node.child.on('error', function (err) { if (err.errno === 'ENOENT') { node.warn('Command not found') } else if (err.errno === 'EACCES') { node.warn('Command not executable') } else { node.log('error: ' + err) } node.status({fill: 'grey', shape: 'dot', text: 'error'}) }) } if (node.redo === true) { var loop = setInterval(function () { if (!node.running) { node.removeListener('input', inputlistener) node.warn('Restarting : ' + node.cmd) runit() } }, 10000) // Restart after 10 secs if required } node.on('close', function (done) { clearInterval(loop) if (node.child != null) { node.child.kill('SIGKILL') } if (RED.settings.verbose) { node.log(node.cmd + ' stopped') } node.status({}) setTimeout(function () { done() }, 100) }) runit() } RED.nodes.registerType('daemon', DaemonNode) }