domotz-remote-pawn
Version:
Domotz Agent
145 lines (129 loc) • 5.09 kB
JavaScript
/** This file is part of Domotz Agent.
* Copyright (C) 2016 Domotz Ltd
*
* Domotz Agent is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Domotz Agent is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Domotz Agent. If not, see <http://www.gnu.org/licenses/>.
**/
/**
* Created by Tommaso Latini <tommaso@domotz.com> on 11/09/15.
*/
var factory = function (q, fs, childProcess, cpu) {
var env = process.env;
var serviceDomotz = env.DOMOTZ_SS_LINK;
var logDir = env.DOMOTZ_LOG_DIR;
function kill(pid, signal) {
signal = (signal !== undefined) ? signal : 'SIGTERM';
console.warn("PROCESS - (%s): Send Signal %s", pid, signal);
process.kill(pid, signal);
}
function gracefulShutdown() {
console.warn('PROCESS - (%s): Graceful Shutdown', process.pid);
setTimeout(function () {
process.exit(1);
}, 100);
}
function restart() {
console.warn("PROCESS - (%s): Rebooting services", process.pid);
var cmd = serviceDomotz,
args = ['restart'],
options = {
detached: true,
stdio: ['ignore', // out and err below
fs.openSync(logDir + '/reboot.log', 'w'),
fs.openSync(logDir + '/reboot_error.log', 'w')]
};
if (process.getuid() !== 0) {
cmd = 'sudo';
args.unshift(serviceDomotz);
}
childProcess.spawn(cmd, args, options).unref();
}
/**
* Same arguments as child_process.spawn. It returns a promise, hiding
* the event emitter behind!
*
* @param command
* @param args
* @param options
* @returns {*|promise}
*/
function spawn(command, args, options) {
if (!command || typeof command !== 'string') {
throw new Error('Command must be a string.');
}
var deferred = q.defer();
cpu.schedule(deferred, command, args, options);
return deferred.promise;
}
/**
* Same arguments as child_process.exec except for the callback.
* It returns a promise!
* This function originally exploited the exec method of child_process.
* We rewrite it because exec it's not efficient, insofar it opens an
* interpreter (by default a shell) and then the command for 2 process in
* total.
*
* @param command
* @param options
* @returns {*|promise}
*
*/
function exec(command, options) {
var argv = command.split(' ');
return spawn(argv[0], argv.slice(1), options);
}
/**
* This is a special case of the spawn() functionality for spawning
* Node processes. In addition to having all the methods in a normal
* ChildProcess instance, the returned object has a communication channel
* built-in. See child.send(message, [sendHandle]) for details.
*
* N.B. THESE CHILD NODES ARE STILL WHOLE NEW INSTANCES OF V8.
* ASSUME AT LEAST 30MS STARTUP AND 10MB MEMORY FOR EACH NEW NODE.
* THAT IS, YOU CANNOT CREATE MANY THOUSANDS OF THEM !!
*
* TODO: Embed this type of call to external process in the scheduler
*
* @param modulePath: The module to run in the child
* @param args: Array List of string arguments
* @param options: Object
* --> cwd: String Current working directory of the child process
* --> env: Object Environment key-value pairs
* --> execPath: String Executable used to create the child process
* --> execArgv: Array List of string arguments passed to the
* executable (Default: process.execArgv)
* --> silent: Boolean
* If true, stdin, stdout, and stderr of the child
* will be piped to the parent,
*
* If false they will be inherited from the parent,
* see the "pipe" and "inherit" options for spawn()'s
* stdio for more details (default is false)
* @returns {*|{send, kill, on}}
*/
function fork(modulePath, args, options) {
var child = childProcess.fork(modulePath, args, options);
console.info('PROCESS - (%s): Forking Module --> %s. Args: %s. Options: %s.',
child.pid, modulePath, args.join(' '), JSON.stringify(options));
return child;
}
return {
kill: kill,
gracefulShutdown: gracefulShutdown,
restart: restart,
exec: exec,
spawn: spawn,
fork: fork
};
};
module.exports.factory = factory;