Stream a command's response up to node - javascript

I'm trying to make a node package which executes a permanent script that keeps printing data and passes it to a package caller.
I use the exec object, in order to call this command:
var exec = require('child_process').exec;
// ...
exec("script always", function(error, stdout, stderr) {
if (error instanceof Error) {
throw error;
}
// here's where everything gets messy
if(callback)
callback(stream)
});
This command keeps printing data until I stop it. Now, how could I stream this console output to a node event another wants to implement? I've been reading about the Readable stream, but I don't know how to tie it all together (actually, heh, they have the function getReadableStreamSomehow() for the sake of the examples).

You should use spawn, not exec, as described here. This will return an object where you have direct access to the program's streams, so you can easily pipe them, e.g., or subscribe to their data events.
See this example for a sample on how to capture output of the curl command.
Hope this helps :-)

Related

Node.js child_process.exect stdout return null, but stderr did not

Currently, I have this simple code that executes java -version to the command line to check if the user has installed Java.
Odd, that when I run this code, stdout gives me nothing, but stderr gives me my desired result.
cprocess.execSync("java -version", (err, stdout, stderr) => {
console.log("stdout: " + stdout); // nothing
console.log("stderr: " + stderr); // output: java version
}
Why is this happening? Do I need to change anything in exec options?
execSync doesn't take a callback argument, but exec does. The text of the question references exec, while the code snippet you shared references execSync, so I'm guessing you meant exec.
Assuming you really meant to use exec, the callback is correct, and the issue isn't with the code, but the java -version command you're calling - that command outputs the information to stderr, not stdout. You could redirect it, but to be honest, I wouldn't bother - you could just use the stderr output.

Integrate Javascript with response

I have two Java scripts and i would like to merge them to get a output that can be treated as successful or failure. I'm not sure if this is the right direction or if i have got this completely wrong.
Initial script is to git clone the repos
const shell = require('shelljs')
const path = '/home/test/'
shell.cd(path)
shell.exec('git clone https://github.com/test/mic.git')
This is a java script and it does clone the repo.
node git.js and it simply clones the repos
Now I have another script which needs to get the result of the above script and pass it to a variable which then says if it is success of failure.
var body = response.getResponseBody();
var res = JSON.parse(body);
if (res.flag < 1){
api.setValue("flag", "failed");
}
Is there a way to integrate these scripts to get the right results.
All i want is if the first script will success/fail and get the status as a result which can be passed as a flag to another variable.
Any directions is really helpful
Shell.exec takes a callback.
If you have an error the code parameter in the callback should be a non-zero
shell.exec('git clone https://github.com/test/mic.git', (code, stdout, stderr) => {
if(code === 0) {
// No Error
} else {
// Had an error
}
})

Node js backend calling a python function

I am in a bit of a fix - I have a node.js app running on my backend, and I have a chunk of code written in Python. This Python program needs to be running constantly in the background, and I need to call a function in this program from the JavaScript code on an API call from some client.
I was thinking of running the Python program as a daemon, but I could not find anything on how I would call a function on that daemon through my javascript code.
I have never worked with daemons either, so at this point, I'm clueless. I would like to know if something like this is possible.
The only other option I can think of have is to switch to Django and maintain the data as part of the Django app itself. I could do this, but I prefer not to. I can not write the Python code in JavaScript because of its dependence on some exclusive libraries that I couldn't find on npm.
If anyone has faced this problem before, please let me know. Thank you!
Here's a simple example (with pip install flask). Assume the function is "is this a real word"; and the heavy prep task is loading the dictionary. Here's code:
from flask import Flask, request, jsonify
app = Flask(__name__)
# heavy loading
dictionary = frozenset(
line.rstrip('\n') for line in open('/usr/share/dict/words'))
# lightweight processing
#app.route('/real_word', methods=['POST'])
def real_word():
result = request.form['word'] in dictionary
return jsonify(result)
# quick-and-dirty start
if __name__ == '__main__':
app.run(host='127.0.0.1', port=7990)
When you run it, you can execute a request to 127.0.0.1:7990/real_word, sending your word as a POST parameter. For example, assuming npm install request:
var request = require('request');
function realWord(word) {
return new Promise(function(fulfill, reject) {
request.post(
'http://127.0.0.1:7990/real_word', {
form: {
word: word
}
},
function (error, response, body) {
if (!error && response.statusCode == 200) {
fulfill(JSON.parse(body));
} else {
reject(error, response);
}
}
);
});
}
realWord("nuclear").then(console.log); // true
realWord("nucular").then(console.log); // false
(Obviously, in an example so simple, reading a list of words is hardly "heavy", and there's really no reason to JSONify a single boolean; but you can take the exactly same structure of code and apply it to wrap pretty much any function, with any kind of input/output you can serialise.)
If it's just for your needs, you can just run the Python program as-is; if you want something that is production-quality, look up how to host a Flask app on a WSGI container, like Gunicorn or mod_wsgi.
You can use node's child process to to call the python script, you could even pipe the result back to javascript if you wish ?
https://nodejs.org/api/child_process.html
https://medium.freecodecamp.com/node-js-child-processes-everything-you-need-to-know-e69498fe970a
Javascript.js
var exec = require('child_process').exec;
cmd = `python python.py` // insert any command line argument
exec(cmd, function(error, stdout, stderr) {
console.log(stdout);
});
Python.py
print("Heyo");
Even tho this example only catches a single output from the console, you could implement a stream.

Node.js alternative to PHP's exec

I want to write a piece of C software (like prime number factorization) and place it on my web-server (based on Node.js).
Then I would like to have an HTML-document with a form and a button.
When the button is clicked the C-program should be executed (on the server) with the a text-field of the form passed as input parameter. The
output of the C-program should be passed to an HTML-textfield again.
In PHP something like this is possible:
<?php
exec('~/tools/myprog.o');
?>
How would I go about something like this in Node.js (Express.js is fine as well). Especially the input/output redirection?
I feel that your question is 2 part.
PHP's exec equivalent for node.js
Execute C program and provide its out put using node.js.
Sticking to pure node.js, you would be able to execute and get access to stdout and stderr with following code.
var exec = require('child_process').exec;
exec("ls -l", function(error, stdout, stderr) {
console.log(error || stdout || stderr);
});
For #2,
I am not sure if you could directly execute a "c" program, so I guess you'd need to do something like this
var exec = require('child_process').exec;
exec("gcc ~/tools/myprog.c -o prime && ./prime", function(error, stdout, stderr) {
console.log(error || stdout || stderr);
});
Above code is definitely not thread safe and if concurrent requests are made, it will break, Ideally you'd not compile it for every request, you'd compile and cache for first request (you can match time stamp of source and compiled output, if compiled output is absent or its time stamp is less - earlier then the source code then you need to compile it) and then use cached output on subsequent requests.
In express you can do something like below
var exec = require('child_process').exec;
router.get('/prime/:num',function(req, res, next){
exec("gcc ~/tools/myprog.c -o prime && ./prime " + req.params.num, function(error, stdout, stderr) {
if(error){
res.status(400).json({'message': error.message});
return;
}
if(stderr){
res.status(400).json({'message': stderr});
return;
}
res.status(200).json({'result': stdout});
});
});
You can play with above code snippets and get what you are looking for.
Hope this helps. Please let me know if you need anything else.

Can't seem to save the output of a client.shell() command to a variable

I am using node-webkit and ADBkit to attempt to read a line from an android build.prop and do something depending on what that line is.
full script at http://pastebin.com/7N7t1akk
The gist of it is this:
var model = client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'" );
alert(model)
i want to read ro.product.model from build.prop into the variable model
As a test im simply attempting to create an alert that displays the return of this shell command, in my case ro.product.model=KFSOWI but whenever i run this script with a connected device the alert returns object Object
edit**
Ive just realized that client.getProperties(serial[, callback]) would probably work better but dont understand these functions (specifically callback) very well
I am very new to this area of Javascripting and home someone can offer some insight
JavaScript is asynchronous programming language, it is built on callbacks. Every function should have callback with data passed to it, if you will watch on documentation, you have client.shell(serial, command[, callback]) so data from executing client.shell() will be passed to callback. You should assign some function that will process callback, for your case will be this
client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'", function(data) {
console.log(data);
});
P.S. there is no alert in nodejs
According to the documentation, you can catch the output in the 2nd argument of client.shell()'s callback:
client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'", function(err, output) {
if (err) {
console.log(err);
}
console.log(output);
});
Use async / await for clearer code.
const data = await client.shell(devices, "su -c 'grep ro.product.model /system/build.prop'" );
console.log(data); // => "Samsung.TM395"
Of course, this only will work if this code is in an async function.
Streamed data.
For streamed data with adbkit, you will need to do a little more to read the entire stream and then output the results, like so:
const stream = await adbClient.shell( config.udid, "ime list -s" ) // adb command to list possible input devices (e.g. keyboards, etc.).
const result = await adb.util.readAll( stream );
console.log( result.toString() ); // => com.sec.android.inputmethod/.SamsungKeypad

Categories