Node js child_process.execFile return - javascript

I need to run a compiled file in C + + with node.js and bring me back a value from this file.
I tried to use child_process.execFile, but I have no problems.
This is the function I use:
var exec = require('child_process');
Test.prototype.write = function (m) {
var wRet;
exec.execFile ('./mainCmd', ['-o', '\\!' + m + '.']
function (error, stdout, stderr) {
wRet = stdout;
console.log ("wRet" + wRet);
return wRet;
});
}
The problem is that the wRet in "console.log" contains text me back from the file c + +, in the "return" remains undefined.
Can you help?
Thank you all!

You have to pass a callback to your test() function:
var chproc = require('child_process');
Test.prototype.write = function(m, cb) {
chproc.execFile(
'./mainCmd',
['-o', '\\!' + m + '.'],
function(error, stdout, stderr) {
if (error) return cb(error);
cb(null, stdout);
}
);
};
// usage ...
var t = new Test();
t.write('foo', function(err, result) {
if (err) throw err;
// use `result`
});

Related

Can I capture the console output in Node.js?

I am trying to kill a process at first, I executed with
exec = require('child_process').exec;
exec('kill xxx', function(error, stdout, stderr) {
if (error) {
console.log('exec error: ', error);
}else{
console.log(stdout)
}
});
I noticed the kill program probably started a child process, whose output cannot be captured here as stdout.
So can I generally capture these console output which seem to be not very relevant with the code?
Stolen: Node: log in a file instead of the console
var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;
console.log = function(d) { //
log_file.write(util.format(d) + '\n');
log_stdout.write(util.format(d) + '\n');
};
ANSWER #2
This message is not created by console.log rather just the Linux system itself. How to catch this?
I think you should be able to do something with fs like so...
var fs = require('fs');
var util = require('util');
var log_file = fs.createWriteStream(__dirname + '/debug.log', {flags : 'w'});
var log_stdout = process.stdout;
const command = 'node your_node_script'; //Whatever you would run in terminal
cp.exec(command, (error, stdout, stderr) => {
if(error) {
log_file.write(error);
}
if(stdout) {
log_file.write(stdout);
}
if(stderr) {
log_file.write(stderr);
}
});

NodeJS - output json array as mutiple json files to disk

I try to use NodeJS to read a JSON array from a JSON file, and then output each JSON object multiple JSON files to the disk.
However, I got the Error EMFILE: too many open files
The array has 20,000 objects.
The code:
function main(){
var clusters_statistics=require("cluster_whole_1.json");
for(var i=0; i<clusters_statistics.length; i++){
var fs=require('fs');
var outputFilename='cut_json/'+i+'.json';
fs.writeFile(outputFilename, JSON.stringify(clusters_statistics[i], null, 4), function(err) {
if(err) {
console.log(err);
} else {
console.log(data);
}
});
}
}
Update:
1. I tried to use the close() function as suggested by Gustavo, unfortunately, it still says "there are too many files open". ("Open" this time).
2. Then I tried recursion inside the close(), and it works now.
The code:
function main(){
clusters_statistics=require("cluster_whole_1.json");
call_close(clusters_statistics.length);
}
function call_close(i){
var fs = require("fs");
var path = 'cut_json/'+i+'.json';
fs.open(path, "w+", function(error, fd) {
if (error) {
console.error("open error: " + error.message);
}else {
fs.writeFile(path, JSON.stringify(clusters_statistics[i], null, 4), function(err) {
if(err) {
console.log(err);
} else {
}
});
fs.close(fd, function(error) {
if (error) {
console.log(err);
} else {
if(i<=0){
return;
}else{
if(i%100==0){
console.log(i);
}
call_close(i-1);
}
}
});
}
});
}
Close the file after you finish writing the Jason into it.
Now you are keeping the files open and filling the memory, if you don't close them manually they will only be closed when your program finishes​.
var fs=require('fs');
function main(){
var clusters_statistics=require("cluster_whole_1.json"); for(var i=0; i<clusters_statistics.length; i++){
var outputFilename='cut_json/'+i+'.json';
var my_file = fs.open(outputFilename, 'w+');
var buffer = new Buffer(JSON.stringify(clusters_statistics[i], null,4):
fs.write(my_file, buffer, 0, buffer.length, null, function(err, written, buffer) {
if(err) {
console.log(err);
} else {
console.log('OK!');
}
});
fs.close(my_file);
}
Opening and closing the file descriptor is not necessary when using fs.writeFile, but you'll probably want to write the files sequentially so you don't open too many files at once.
function write_cluster_statistics(clusters_statistics, callback, index) {
index = index || 0;
if (index >= clusters_statistics.length) {
return callback();
}
var fs = require('fs');
var path = 'cut_json/' + index + '.json';
var content = JSON.stringify(clusters_statistics[index], null, 4);
fs.writeFile(path, content, function (err) {
if (err) {
callback(err);
} else {
write_cluster_statistics(clusters_statistics, callback, index + 1);
}
});
}
function main() {
var clusters_statistics = require("cluster_whole_1.json")
write_cluster_statistics(clusters_statistics, function (err) {
if (err) {
console.error(err);
} else {
console.log('done');
}
});
}

Unable to export variables in async node js files to other nodejs files [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 5 years ago.
I am trying to export variable output to another node js file. But due to async task of fs read function, I am unable to export output variable.
I am unable to understand where I am making mistake.
I am just getting output as undefined.
Could anyone let me know the mistake.
var parseString = require('xml2js').parseString;
var xml = '';
var fs = require('fs');
var async = require('async');
var exports = module.exports = {};
var output;
var out;
async.series([
function (callback) {
fs.readFile('./sample.xml', 'utf8', function(err, data) {
parseString(data, function(err, result) {
xml = result;
var partyNames = xml["TXLife"]["TXLifeRequest"][0]["OLifE"][0]["Party"];
for (var i = 0;i < partyNames.length;i++) {
var firstName, lastName, sex, dob, zip, riskScore, scriptCheckScore, questCheckScore;
if (partyNames[i]["PartyTypeCode"][0]["_"] == "Person" && partyNames[i]["Person"][0]["LastName"] == "JAYME") {
if (partyNames[i]["Person"][0].hasOwnProperty("FirstName")) {
firstName = partyNames[i]["Person"][0]["FirstName"];
}
if (partyNames[i]["Person"][0].hasOwnProperty("LastName")) {
lastName = partyNames[i]["Person"][0]["LastName"];
}
if (partyNames[i]["Person"][0].hasOwnProperty("BirthDate")) {
dob = partyNames[i]["Person"][0]["BirthDate"];
}
if (partyNames[i]["Person"][0].hasOwnProperty("Gender") && partyNames[i]["Person"][0]["Gender"][0].hasOwnProperty("_")) {
sex = partyNames[i]["Person"][0]["Gender"][0]["_"]
}
if (partyNames[i].hasOwnProperty("Address") && partyNames[i]["Address"][0].hasOwnProperty("Zip")) {
zip = partyNames[i]["Address"][0]["Zip"][0];
}
if (partyNames[i].hasOwnProperty("Risk") && partyNames[i]["Risk"][0].hasOwnProperty("OLifEExtension") &&
partyNames[i]["Risk"][0]["OLifEExtension"][5].hasOwnProperty("RiskScoring") && partyNames[i]["Risk"][0]["OLifEExtension"][5]["RiskScoring"][0].hasOwnProperty("RiskScore")) {
riskScore = partyNames[i]["Risk"][0]["OLifEExtension"][5]["RiskScoring"][0]["RiskScore"][0]["QuantitativeScore"][0];
scriptCheckScore = partyNames[i]["Risk"][0]["OLifEExtension"][5]["RiskScoring"][0]["RiskScore"][1]["QuantitativeScore"][0];
questCheckScore = partyNames[i]["Risk"][0]["OLifEExtension"][5]["RiskScoring"][0]["RiskScore"][2]["QuantitativeScore"][0]
console.log("Risk score ",riskScore);
console.log("Script check score ",scriptCheckScore);
console.log("questCheckScore ",questCheckScore);
}
output = firstName + " " + lastName + " " + dob + " " + sex + " " + zip;
callback(null, output);
}
}
})
});
},
function (callback){
out = output;
//module.exports.out = output;
console.log("second");
callback(null, out);
}
],
function(err, result) {
console.log("result", result);
exports.out = result;
}
);
From Module A you will want to invoke a function in Module B (let's call it getFileContent) that takes a callback function - maybe something like this:
var getFileContent(callback) {
:
// async operation to get content
callback(null, results); // assuming no error
:
}
Now in Module A, invoke this - something like this:
var B = require('B'); // whatever module B reference is
B.getFileContent(function(err, result) {
if (err) {
:
} else {
// do something with result
}
});
You are exporting nothing right now because you're calling a function asynchronously, so you should be exporting your function instead of an empty object. For example:
In your main file
var awesomeExports = require('seriesFile');
awesomeExports((err, value) => {
if(err) //Do something with error.
//Do something with value.
})
In your async.series file
//All your includes.
module.exports = (err, callback) => {
async.series([
//Your async.series functions in the array.
],
function(err, result) {
callback(err, result);
}
);
}

Node.js print directory files

Currently working on a small project and having a few issues with getting files to print onto the page.
Currently, all files within my /views directory will print, however, I am wanting to expand this so it can print files within folders, for example, /views/test/prototype.html.
module.exports = function (router) {
var fs = require('fs');
router.get('/file-list', function (req, res) {
var markup = function (files, callback) {
var items = [];
for (i = 0; i < files.length; i++) {
var q = files[i];
q = q.slice(0, -5);
var markup = '<li>' + '' + q + '' + '</li>';
items.push(markup);
};
callback(items);
};
var getFiles = function (callback) {
fs.readdir(__dirname + '/views', function (err, files) { // '/' denotes the root folder
if (err) throw err;
markup(files, callback)
});
};
getFiles(function (items) {
// render markup for items
res.render('file-list', { 'files': items });
});
});
}
Inside your getFiles method, you can add some extra logic to see if the file that you are currently parsing is a directory, case in which you can loop over the files in that directory and push them to a result set array (filesArray). My example below only takes into account level 2 folders, such as in the /views/test/prototype.html scenario that you provided:
module.exports = function (router) {
var fs = require('fs');
router.get('/file-list', function (req, res) {
var markup = function (files, callback) {
var items = [];
for (i = 0; i < files.length; i++) {
var q = files[i];
q = q.slice(0, -5);
var markup = '<li>' + '' + q + '' + '</li>';
items.push(markup);
};
callback(items);
};
var getFiles = function (callback) {
var rootDir = __dirname + '/views';
fs.readdir(rootDir, function (err, files) { // '/' denotes the root folder
if (err) throw err;
// Subdirectory parsing logic START
var filesArray = [];
for (var i = 0; i < files.length; i++) {
var subdirPath = rootDir + '/' + files[i];
fs.stat(subdirPath, function (err, stats) {
if (err) {
console.log(err);
throw err;
}
if (stats.isDirectory()) {
fs.readdir(subdirPath, function (err, subdirFiles) {
if (err) throw err;
Array.prototype.forEach.call(subdirFiles, function (file) {
filesArray.push(file);
});
});
} else {
filesArray.push(files[i]);
}
});
}
// Subdirectory parsing logic END
markup(filesArray, callback)
});
};
getFiles(function (items) {
// render markup for items
res.render('file-list', {
'files': items
});
});
});
}
The above example is a crude one, as it would be recommended to use a mechanism such as Promises that allows you to better control the asynchronous looping going around and make sure that you have parsed all the individual files before calling markup().
UPDATE #1
I've been trying various approaches for trying to crawl all directories and subdirectories using promises, with no success, but I did manage to come across a working solution for your scenario in this Stack Overflow accepted answer - to be more precise, it's the parallel search mechanism provided in the aforementioned answer.
Below is an adaptation of the parallel search mechanism blended in with your existing code base - I've tested it and it works as intended:
var fs = require('fs');
var path = require('path');
module.exports = function (router) {
router.get('/file-list', function (req, res) {
var getFiles = function (callback) {
var rootDir = path.join(__dirname, 'views');
walk(rootDir, function (err, results) {
if (err) {
console.log(err);
return;
}
markup(results, callback);
});
};
var walk = function (dir, done) {
var results = [];
fs.readdir(dir, function (err, list) {
if (err) {
return done(err);
}
var pending = list.length;
if (!pending) {
return done(null, results);
}
list.forEach(function (file) {
file = path.resolve(dir, file);
fs.stat(file, function (err, stat) {
if (stat && stat.isDirectory()) {
walk(file, function (err, res) {
results = results.concat(res);
if (!--pending) {
done(null, results);
}
});
} else {
results.push(file);
if (!--pending) {
done(null, results);
}
}
});
});
});
};
var markup = function (files, callback) {
var items = [];
for (i = 0; i < files.length; i++) {
var q = files[i];
q = q.slice(0, -5);
var markup = '<li>' + '' + q + '' + '</li>';
items.push(markup);
};
callback(items);
};
getFiles(function (items) {
// render markup for items
res.render('file-list', {
'files': items
});
});
});
};
You need to examine files array with fs.stat and recursively do getFiles on directories.
This answer solves similar problem

node.js async function in loop?

I am having some problems with node.js. What I'm trying to do is get an array of the directories in "./"+req.user.email and loop through them finding out their size and adding a table row to output, as you can see in the code. At the end I wan't to send all the table rows using res.send().
However the only output I am getting is:
<tr></tr>
for each file in the array. It seems that the forEach function is not waiting for readSizeRecursive at all. The readSizeRecursive function is asynchronous, and I believe that is what's causing the problem, but I don't know how I can fix this.
Any help would be greatly appreciated, I have included the readSizeRecursive function too. Thank you!
var output = "";
fs.readdir("./" + req.user.email, function (err, files) {
files.forEach(function(file){
output += "<tr>";
readSizeRecursive("./"+req.user.email+"/"+file, function (err, total){
output += '<td>' + file + '</td><td>' + total + '</td>';
});
output += "</tr>"
});
res.send(output)
});
readSizeRecursive() :
// Function to find the size of a directory
function readSizeRecursive(item, cb) {
fs.lstat(item, function(err, stats) {
var total = stats.size;
if (!err && stats.isDirectory()) {
fs.readdir(item, function(err, list) {
async.forEach(
list,
function(diritem, callback) {
readSizeRecursive(path.join(item, diritem), function(err, size) {
total += size;
callback(err);
});
},
function(err) {
cb(err, total);
}
);
});
}
else {
cb(err, total);
}
});
}
Please use the async module for this kind of pattern. Using async.each will allow you to compute the size for each folder asynchronously, and then return the sizes once you're done computing everything individually.
var output = [];
fs.readdir('./' + req.user.email, function (err, files) {
async.each(compute, report);
});
function compute (file, done) {
// calculate size, then callback to signal completion
// produce a result like below, then invoke done()
var obj = { files: [
{ name: file, size: size },
{ name: file, size: size },
{ name: file, size: size }
]};
output.push(obj);
done();
}
// doesn't need to be this awful
function format (list) {
var result = [];
list.forEach(function (item) {
var description = item.files.map(function (file) {
return util.format('<td>%s</td><td>%s</td>', file.name, file.size);
});
result.push(description);
});
result.unshift('<tr>');
result.push('</tr>');
return result.join('</tr><tr>');
}
function report (err) {
if (err) { return next(err); }
var result = format(output);
res.send(result);
}
This way you can easily swap out the different pieces of functionality, changing the formatting without altering the computing of the file size tree, for example.
Your main issue was control flow. You return with res.send while you are asynchronously looping and figuring out the sizes.
var fs = require ("fs");
var createTableContent = function (p, cb){
var read = function (p, cb){
//Prevent recursion if error
if (err) return cb ();
fs.stat (p, function (error, stats){
if (error){
err = error;
return cb ();
}
if (stats.isDirectory ()){
var dirSize = 0;
fs.readdir (p, function (error, entries){
if (error){
err = error;
return cb ();
}
var pending = entries.length;
//Empty dir
if (!pending) return cb (0);
entries.forEach (function (entry){
read (p + "/" + entry, function (entrySize){
dirSize += entrySize;
if (!--pending) return cb (dirSize);
});
});
});
}else{
cb (stats.size);
}
});
};
//A lot of errors can be produced, return only the first one
var err = null;
//Suppose p is a dir
fs.readdir (p, function (error, entries){
if (error) return cb (error);
var content = "";
var pending = entries.length;
if (!pending) return cb (null, content);
entries.forEach (function (entry){
read (p + "/" + entry, function (totalSize){
if (err) return cb (err);
content += "<tr><td>" + entry + "</td><td>" + totalSize + "</td></tr>";
if (!--pending){
//End
cb (null, content);
}
});
});
});
};
//Here goes the "email" path
createTableContent (".", function (error, content){
if (error) return console.error (error);
console.log (content);
});

Categories

Resources