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 bashstdout
output, 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