Node.js can't get output of spawned process - javascript

This code get output of spawned process. What is wrong? node version is v0.10.22
var spawn = require('child_process').spawn;
var what = 'java';
var spawned = spawn(what, ['-version']);
console.log('starting `'+what+' -version`');
spawned.stdout.setEncoding('utf8');
spawned.stdout.on('data', function (data) {
console.log(data);
});
spawned.on('close', function (code) {
console.log('process exit code ' + code);
});
var whendone = function() {
console.log('done');
};
setTimeout(whendone,5000);
As you can see I even added some timeout to wait for a launched process to finish.

java -version writes to stderr.

Related

Python to NodeJS communication not working through spawn

I'm trying to replicate this process to establish communication be nodejs and python through stdin and stdout : https://healeycodes.com/javascript/python/beginners/webdev/2019/04/11/talking-between-languages.html
Context:
Sender - which is giving output to stdout
Listener - one who's reading it
Now, when Python is sender and NodeJS is Listener isn't working. NodeJS gives no output.
On further digging my issue is very similar to Not receiving stdout from nodejs spawned process except I don't need unbuffered output as such. Tried sol from last ques.. didn't work.
Here are files:
sensor.py
import random, time
import sys
time.sleep(random.random() * 5) # wait 0 to 5 seconds
temperature = (random.random() * 20) - 5 # -5 to 15
print(temperature, flush=True, end='')
sys.stdout.flush()
listener.js
const { spawn } = require('child_process');
//spawn()
const child = spawn('python', ['path-to-sensor.py']);
console.log('Here');
child.stdout.on('data', function(data) {
console.log('Got the data')
console.log(data)
});
child.on('error', function () {
console.log("Failed to start child.");
});
child.on('close', function (code) {
console.log('Child process exited with code ' + code);
});
child.stdout.on('end', function () {
console.log('Finished collecting data chunks.');
});
Reason: Event listener - child.stdout.on('data', callback) is never called
What I want the output to be:
Store the stdout from sensor.py in a variable
Can't figure out what else I can do to fix this
In sensor.py you are not using the right syntax in your code:
print(temperature, flush=True, end='')
The right syntax is:
print(object(s), sep=separator, end=end, file=file, flush=flush)
Source
If you left the code in sensor.py as:
print(temperature)
And in listener.js as:
child.stdout.on('data', function(data) {
console.log('Got the data')
//console.log(data)
console.log(data.toString('utf8'))
});
It works ok

Node - child process spawn path

I would like to run an exe in Windows from my Node Webkit app.
I am trying the below code but it is not working.
document.getElementById('play').onclick = function()
{
var spawn = require('child_process').spawn;
var child = spawn(__dirname + '/core.exe', ['/arg1']);
var snd = new Audio("min.wav");
snd.play();
win.minimize();
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
child.on('close', function (code) {
console.log('child process exited with code ' + code);
var snd = new Audio("restore.wav");
snd.play();
win.restore();
});
}
Am I getting the path wrong? I need it to be current directory and run the exe with that name and the example arg.
The output SHOULD be a messagebox, but nothing loads.
Managed to figure it out, it wasn't defined because I was using it in browser context. I didn't get the nw.js SDK version for some reason, found that __DIRNAME was undefined. Came up with this solution instead.
var path = require('path');
var nwDir = path.dirname(process.execPath);
var spawn = require('child_process').spawn;
var child = spawn(nwDir + '/app/core.exe', ['/arg1']);
Now working as intended.

node.js listen to process error event

There is a way somehow to listen to event for node process
like process.stderr, I want event that when this line is invoked to do some logic inside, any idea if it possible ?
If you mean to listen to the child process spawned from your nodejs server, its simple, i have given the example below.
Note: its very unclear to guess what you mean
var spawn = require('child_process').spawn;
var child = spawn('myshell.sh', []);
child.stdout.on('data', function(data) {
console.log('stdout- ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr- ' + data);
});
child.on('exit', function (code) {
console.log('exit - ' + code);
});

exec 'node app' hangs inside gulp task

This gulp task hangs on exec('node config/app') line. first exec works fine but the second just hangs.
gulp.task('test', function(cb) {
var exec = require('child_process').exec;
exec('echo 3', function(err, stdout) {
console.log(stdout);
});
exec('node config/app', function(err, stdout, stderr) {
console.log(stdout);
var testemOptions = {
file: 'testem.json'
};
var t = new testem();
return t.startCI(testemOptions, function() {
cb();
});
});
});
I can see the output 3 but no output is shown for the second console.log.
I am trying to run my server before running the tests with testem.
I've tried this similar solution but it doesn't work: Exec not returning anything when trying to run git shortlog with nodejs.
Also I've recently asked a hanging testem gulp task question: Testem gulp task hangs after finished.
Edit:
My current solution is:
gulp.task('test', /*['build'],*/ function(cb) {
var spawn = require('child_process').spawn;
var proc = spawn('node', ['config/app']);
proc.stdout.on('readable', function() {
var output = proc.stdout.read();
if (output && output.toString().match('express listening')) {
var testemOptions = {
file: 'testem.json'
};
var t = new testem();
t.startCI(testemOptions, function() {
proc.kill();
cb();
});
}
});
});
If you want to use testem to test the "node config/app" server, you cannot use exec.
Exec is supposed to callback when the command is finished so in your case it will never callback.
try with
gulp.task('test', function(cb) {
var spawn = require('child_process').spawn;
var proc = spawn('node', ['config/app']);
var testStarted = false;
proc.stdout.on('readable', function() {
if (testStarted) return;
testStarted = true;
var testemOptions = {
file: 'testem.json'
};
var t = new testem();
t.startCI(testemOptions, function() {
proc.kill()
cb();
});
}
});
Note that I did not test this code and that it probably does not handle all the corner cases you might encounter (if the server stops unexpectedly for example)
you may also want to check the plugin https://github.com/sargentsurg/gulp-testem
There is ŧestem plugin on github.

Stream child process output in flowing mode

I have custom command line written using Python which prints its output using "print" statement. I am using it from Node.js by spawning a child process and sending commands to it using child.stdin.write method. Here's source:
var childProcess = require('child_process'),
spawn = childProcess.spawn;
var child = spawn('./custom_cli', ['argument_1', 'argument_2']);
child.stdout.on('data', function (d) {
console.log('out: ' + d);
});
child.stderr.on('data', function (d) {
console.log('err: ' + d);
});
//execute first command after 1sec
setTimeout(function () {
child.stdin.write('some_command' + '\n');
}, 1000);
//execute "quit" command after 2sec
//to terminate the command line
setTimeout(function () {
child.stdin.write('quit' + '\n');
}, 2000);
Now the issue is I am not receiving the output in flowing mode. I want get the output from child process as soon as it's printed but I am receiving the output of all the commands only when child process is terminated (using custom cli's quit command).
You need to flush the output in the child process.
Probably you think this isn't necessary because when testing and letting the output happen on a terminal, then the library flushes itself (e. g. when a line is complete). This is not done when printing goes to a pipe (due to performance reasons).
Flush yourself:
#!/usr/bin/env python
import sys, time
while True:
print "foo"
sys.stdout.flush()
time.sleep(2)
The best way is to use unbuffered mode of python standard output. It will force python to write output to output streams without need to flush yourself.
For example:
var spawn = require('child_process').spawn,
child = spawn('python',['-u', 'myscript.py']); // Or in custom_cli add python -u myscript.py
child.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
In my case in Python I'm using sys.stdin.readline and yielding last line:
def read_stdin():
'''
read standard input
yeld next line
'''
try:
readline = sys.stdin.readline()
while readline:
yield readline
readline = sys.stdin.readline()
except:
# LP: avoid to exit(1) at stdin end
pass
for line in read_stdin():
out = process(line)
ofp.write(out)
sys.stdout.flush()
and when in Node.js
var child = spawn(binpath, args);
// register child process signals
child.stdout.on('data', function (_data) {
var data = Buffer.from(_data, 'utf-8').toString().trim();
console.log(data);
});
child.stderr.on('data', function (data) {
console.warn('pid:%s stderr:%s', child.pid, data);
});
child.stdout.on('exit', function (_) {
console.warn('pid:%s exit', child.pid);
});
child.stdout.on('end', function (_) {
console.warn('pid:%s ended', child.pid);
});
child.on('error', function (error) {
console.error(error);
});
child.on('close', (code, signal) => { // called after `end`
console.warn('pid:%s terminated with code:%d due to receipt of signal:%s with ', child.pid, code, signal);
});
child.on('uncaughtException', function (error) {
console.warn('pid:%s terminated due to receipt of error:%s', child.pid, error);
});

Categories