I'm running a command in node.js using child_process.spawn. This command has an interactive mode, so that can get the stdin to take input from the console and output results to stdout. I'm using this mode, to send commands to this child via the child.stdin.write( data+'\r\n' );.
-
I suppose to get the results in the callback
child.stdout.on('data'), but it seems I'm not getting all data wrote by the command, that I can see in the bashstdoutoutput, but not in thecallback. -
I would like a way to retrieve the data sent with
child.stdin.write( data+'\r\n' );in order to get the tuple/struct (data,result), since the execution is asynchronous.
For convenience, I have added a callback for the child.stdout.on('data') to get results outside that scope. My code looks like:
var exec = function(name,command,params,options,callback) {
var self=this;
/** default ChildProcess options
* @see https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options
*/
var _options = {
// Prepare child to run independently of its parent process
//detached: true
};
for (var attrname in options) { _options[attrname] = options[attrname]; }
var created_time= ( new Date() ).toISOString();
var task = require('child_process').spawn(command, params, _options);
task.stdout.on('data', function(result) {
var out=new Buffer(result,'utf-8').toString();
callback(out);
});
task.on('error', function(error) {
if(self.logger) self.logger.error("exec:%s pid:%d error:\n%@",name,task.pid,error);
});
task.on('uncaughtException', function (error) {
if(self.logger) self.logger.error("exec:%s pid:%s uncaughtException:\n%@",name,task.pid,error);
});
task.stdout.on('end', function(data) {
if(self.logger) self.logger.debug("exec:%s end.",name);
});
task.stderr.on('data', function(data) {
if(self.logger) self.logger.debug("exec:%s stderr:%s",name,data);
});
task.on('close', (code, signal) => {
if(self.logger) self.logger.warn('task:%s pid:%s terminated due to receipt of signal:%s',name,task.pid,signal);
});
task.on('exit', function(code) {
if(self.logger) self.logger.debug("exec:%s exit.",name);
if (code != 0) {
var error=new Error();
error.description= command + ' ' + params.join(' ');
error.code=code;
if(self.logger) self.logger.error("exec:%s pid:%d error:\n%@",name,task.pid,error);
}
// at exit explicitly kill exited task
task.kill('SIGINT');
});
return task;
}//exec
// load child task
var load = function(model,callback) {
var m=exec('fasttext','./fasttext', ['predict', model, '-'], {}, callback);
m.stdout.pipe(process.stdout);
return m;
}//load
// send data to child task
var send = function(task,data) {
task.stdin.setEncoding('utf-8');
task.stdin.write( data );
task.stdin.write('\r\n');
}//send
I run the command like
var model=load(modelFile,
function(result) {
console.log(result);
});
send(model,result);
NOTE.
In this specific case the command was fasttext a command line classification utility by Facebook Inc., that can run in interactive mode when called like ./fasttext predict filePath -.
via loretoparisi
No comments:
Post a Comment