(Node.js) How to store stdout.pipe into a variable? - node.js

I want to get free -m (linux shell command) and store its result into a variable
by using source code below:
var spawn = require('child_process').spawn,
command = spawn('free', ['-m']);
command.stdout.pipe(process.stdout);
Is there any way to store process.stdout in a variable, please me some suggestions

This is fairly simple with child_process.exec:
var child = require("child_process");
var freeOut;
child.exec("free", ["-m"], function (error, stdout, stderr) {
if (error) {
console.error(error, stderr);
return;
}
//stdout and stderr are available here
freeOut = stdout;
process.stdout.write(stdout);
});
//Note. Do NOT use freeOut here. exec is async. Can only use in the callback

Related

Run Bash-Script within Electron App using child_process.exec

I'm struggling with running a bash-script within main.html.
const exec = require("child_process").exec;
// Execute bash script
exec("/c/workspace/_edu_zone/Proxy_Manager/filemover.sh", shellCallback);
// Callback
function shellCallback(error, stdout, stderr) {
console.log(error, stdout)
}
I'm always getting the error: no such file or directory. What am i doing wrong?
Any help is highly appreciated.
change
/c/workspace/_edu_zone/Proxy_Manager/filemover.sh
to
c:/workspace/_edu_zone/Proxy_Manager/filemover.sh
or
your could try using node-powershell to execute the command directly
const shell = require('node-powershell')
let ps = new shell({
executionPolicy: 'Bypass',
noProfile: true
});
function lunchnode() {
process.stdout.write('logging');
ps.addCommand('node run.js')
ps.invoke()
.then(function (output) {
process.stdout.write(output)
}).catch(function (err) {
process.stdout.write(err)
ps.dispose()
})
}

nodejs child_process spawn command input file

I would like to run the following code in nodejs
$ ./a.out < inputfile.txt
So I wrote the following code.
var run = spawn('./a.out', ['< input.txt']);
var run = spawn('./a.out < input.txt');
I tried this, but it did not work.
What I want to do is to input input.txt ina.out
how can i do?
Since < (redirection) is a shell construct, you need to run your command line with a shell. That's what child_process.exec() is for:
const exec = require('child_process').exec;
exec('./a.out < inputfile.txt', function(err, stdout, stderr) {
if (err) {
return console.error('exec error:', err);
}
console.log('stdout:', stdout);
console.log('stderr:', stderr);
});

Run shell command and reply to questions

I've a shell script that, when started, asks for credentials.
I would like to start my script with Node.js using exec() and send the credentials when asked.
Currently my code is this:
var sys = require('sys')
var exec = require('child_process').exec;
function puts(error, stdout, stderr) { sys.puts(stdout) }
exec("myscript", puts);
Is it possible?
n.b. I can't pass the credentials as arguments of the script, it doesn't support them.
You should write to the stdin of the process. This is an example with exec:
var exec = require('child_process').spawn;
var child = spawn('script');
child.stdin.setEncoding('utf8');
child.stdout.on('data', function (data) {
if (data.toString() === 'enter the password:'){
child.stdin.write('pass');
return child.stdin.end();
}
console.log('got some other data:');
console.log(data.toString())
});
Similar to this question.

Exec : display stdout "live"

I have this simple script :
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee', function(error, stdout, stderr) {
console.log(stdout);
});
where I simply execute a command to compile a coffee-script file. But stdout never get displayed in the console, because the command never ends (because of the -w option of coffee).
If I execute the command directly from the console I get message like this :
18:05:59 - compiled my_file.coffee
My question is : is it possible to display these messages with the node.js exec ? If yes how ? !
Thanks
Don't use exec. Use spawn which is an EventEmmiter object. Then you can listen to stdout/stderr events (spawn.stdout.on('data',callback..)) as they happen.
From NodeJS documentation:
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code.toString());
});
exec buffers the output and usually returns it when the command has finished executing.
exec will also return a ChildProcess object that is an EventEmitter.
var exec = require('child_process').exec;
var coffeeProcess = exec('coffee -cw my_file.coffee');
coffeeProcess.stdout.on('data', function(data) {
console.log(data);
});
OR pipe the child process's stdout to the main stdout.
coffeeProcess.stdout.pipe(process.stdout);
OR inherit stdio using spawn
spawn('coffee -cw my_file.coffee', { stdio: 'inherit' });
There are already several answers however none of them mention the best (and easiest) way to do this, which is using spawn and the { stdio: 'inherit' } option. It seems to produce the most accurate output, for example when displaying the progress information from a git clone.
Simply do this:
var spawn = require('child_process').spawn;
spawn('coffee', ['-cw', 'my_file.coffee'], { stdio: 'inherit' });
Credit to #MorganTouvereyQuilling for pointing this out in this comment.
Inspired by Nathanael Smith's answer and Eric Freese's comment, it could be as simple as:
var exec = require('child_process').exec;
exec('coffee -cw my_file.coffee').stdout.pipe(process.stdout);
I'd just like to add that one small issue with outputting the buffer strings from a spawned process with console.log() is that it adds newlines, which can spread your spawned process output over additional lines. If you output stdout or stderr with process.stdout.write() instead of console.log(), then you'll get the console output from the spawned process 'as is'.
I saw that solution here:
Node.js: printing to console without a trailing newline?
Hope that helps someone using the solution above (which is a great one for live output, even if it is from the documentation).
I have found it helpful to add a custom exec script to my utilities that do this.
utilities.js
const { exec } = require('child_process')
module.exports.exec = (command) => {
const process = exec(command)
process.stdout.on('data', (data) => {
console.log('stdout: ' + data.toString())
})
process.stderr.on('data', (data) => {
console.log('stderr: ' + data.toString())
})
process.on('exit', (code) => {
console.log('child process exited with code ' + code.toString())
})
}
app.js
const { exec } = require('./utilities.js')
exec('coffee -cw my_file.coffee')
After reviewing all the other answers, I ended up with this:
function oldSchoolMakeBuild(cb) {
var makeProcess = exec('make -C ./oldSchoolMakeBuild',
function (error, stdout, stderr) {
stderr && console.error(stderr);
cb(error);
});
makeProcess.stdout.on('data', function(data) {
process.stdout.write('oldSchoolMakeBuild: '+ data);
});
}
Sometimes data will be multiple lines, so the oldSchoolMakeBuild header will appear once for multiple lines. But this didn't bother me enough to change it.
child_process.spawn returns an object with stdout and stderr streams.
You can tap on the stdout stream to read data that the child process sends back to Node. stdout being a stream has the "data", "end", and other events that streams have. spawn is best used to when you want the child process to return a large amount of data to Node - image processing, reading binary data etc.
so you can solve your problem using child_process.spawn as used below.
var spawn = require('child_process').spawn,
ls = spawn('coffee -cw my_file.coffee');
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data.toString());
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data.toString());
});
ls.on('exit', function (code) {
console.log('code ' + code.toString());
});
Here is an async helper function written in typescript that seems to do the trick for me. I guess this will not work for long-lived processes but still might be handy for someone?
import * as child_process from "child_process";
private async spawn(command: string, args: string[]): Promise<{code: number | null, result: string}> {
return new Promise((resolve, reject) => {
const spawn = child_process.spawn(command, args)
let result: string
spawn.stdout.on('data', (data: any) => {
if (result) {
reject(Error('Helper function does not work for long lived proccess'))
}
result = data.toString()
})
spawn.stderr.on('data', (error: any) => {
reject(Error(error.toString()))
})
spawn.on('exit', code => {
resolve({code, result})
})
})
}

Node.js: Object value as stdout of child_process.exec

I'm new to Node and stumbling on some of the nonblocking elements of it. I'm trying to create a object and have one of the elements of it being a function that returns the stdout of a child_process.exec, like so:
var exec = require('child_process').exec;
var myObj = {};
myObj.list = function(){
var result;
exec("ls -al", function (error, stdout, stderr) {
result = stdout;
});
return result;
}
console.log('Ta da : '+myObj.list);
I figure that myObj.list is returning result before it is set as stdout, but I can't figure out how to make it wait or do a callback for it. Thanks for your help!
You can't directly return the value as it's not going to be available for a bit. So instead of a return value you need to use a callback which means turning the calling code inside out a bit.
var exec = require('child_process').exec;
var myObj = {};
myObj.list = function(callback){
var result;
exec("ls -al", function (error, stdout, stderr) {
callback(stdout);
});
// No return at all!
}
// Instead of taking a return we pass a callback
// which receives the value and carries on our computation.
myObj.list(function (stdout) {
console.log('Ta da : '+ stdout);
});
In real code you'd probably want to have your callback take an error as its first argument, you don't have to but it's the normal way things are done in Node.JS.

Resources