Would it be possible to run a batch file from a nodejs application?
After googling for some time we can use child_process to execute the commands. Tried the same module but without success.
Could somebody guide me?
This creates a NodeJS module with a single function named exec() to execute batch scripts.
var exec = require('child_process').exec,
path = require('path'),
os = require('os');
fs = require('fs');
// HACK: to make our calls to exec() testable,
// support using a mock shell instead of a real shell
var shell = process.env.SHELL || 'sh';
// support for Win32 outside Cygwin
if (os.platform() === 'win32' && process.env.SHELL === undefined) {
shell = process.env.COMSPEC || 'cmd.exe';
}
// Merges the current environment variables and custom params for the environment used by child_process.exec()
function createEnv(params) {
var env = {};
var item;
for (item in process.env) {
env[item] = process.env[item];
}
for(item in params) {
env[item] = params[item];
}
return env;
}
// scriptFile must be a full path to a shell script
exports.exec = function (scriptFile, workingDirectory, environment, callback) {
var cmd;
if (!workingDirectory) {
callback(new Error('workingDirectory cannot be null'), null, null);
}
if (!fs.existsSync(workingDirectory)) {
callback(new Error('workingDirectory path not found - "' + workingDirectory + '"'), null, null);
}
if (scriptFile === null) {
callback(new Error('scriptFile cannot be null'), null, null);
}
if (!fs.existsSync(scriptFile)) {
callback(new Error('scriptFile file not found - "' + scriptFile + '"'), null, null);
}
// transform windows backslashes to forward slashes for use in cygwin on windows
if (path.sep === '\\') {
scriptFile = scriptFile.replace(/\\/g, '/');
}
// TODO: consider building the command line using a shell with the -c argument to run a command and exit
cmd = '"' + shell + '" "' + scriptFile + '"';
// execute script within given project workspace
exec(cmd,
{
cwd: workingDirectory,
env: createEnv(environment)
},
function (error, stdout, stderr) {
// TODO any optional processing before invoking the callback
callback(error, stdout, stderr);
}
);
};
I have found the solution for it.. and its works fine for me. This opens up a new command window and runs my main node JS in child process. You need not give full path of cmd.exe. I was making that mistake.
var spawn = require('child_process').spawn,
ls = spawn('cmd.exe', ['/c', 'startemspbackend.bat']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('exit', function (code) {
console.log('child process exited with code ' + code);
});
An easier way I know for executing that is the following code :
function Process() {
const process = require('child_process');
var ls = process.spawn('script.bat');
ls.stdout.on('data', function (data) {
console.log(data);
});
ls.stderr.on('data', function (data) {
console.log(data);
});
ls.on('close', function (code) {
if (code == 0)
console.log('Stop');
else
console.log('Start');
});
};
Process();
Related
I have an array with some IDs like a = [abc,cde,efg]. I pass this array and a second one containing the names with fit to the IDs to a child process in Node.
I want to wait until the child process finished and processes the next array member after that.
The code to achieve it is (with the suggested Edit):
function downloadSentinel(promObj) {
return new Promise((resolve,reject) => {
function makeRequest(url, i, callback) {
url = promObj.ID;
name = promObj.Name;
var sys = require('util'),
exec = require('child_process').exec,
child;
var directory = __dirname.substring(0, __dirname.indexOf("\\app_api"));
console.log(directory);
child = exec(directory + '\\downloadProducts.sh' + promObj.ID[i] + ' ' + promObj.Name[i], function (error, stdout, stderr) {
child.on("error", function (error) {
console.log(error);
})
child.stdout.on('data', function (data) {
console.log(data.toString());
});
child.on('exit', function(exit) {
console.log(exit);
callback();
})
})
}
async.eachOfLimit(promObj.requestURLS, 2, makeRequest, function (err) {
if (err) reject(promObj)
else {
resolve(promObj);
}
});
});
}
I am using npm-async to control the concurrency flow because I want to limit the curl requests I do inside the shell script. The shell sript works without an error. Now the script is only called twice because of the async.eachOfLimit limit. Then the other array IDs are not processed anymore.
EDIT
This is the code I tried at last, but then all possible urls are evoked instead of only 2. I found this here Another Stackoverflow question. I also tried with async.timesLimit
function downloadSentinel(promObj,req,res) {
async.eachOfLimit(promObj.requestURLS, 2,function (value,i,callback) {
console.log('I am here ' + i + 'times');
url = promObj.requestURLS;
name = promObj.Name;
console.log(promObj.requestURLS);
var sys = require('util'),
exec = require('child_process').exec,
child;
var directory = __dirname.substring(0, __dirname.indexOf("\\app_api"));
console.log(directory);
console.log("executing:", directory + '\\downloadProducts.sh ' + promObj.requestURLS[i] + ' ' + promObj.Name[i]);
child = exec(directory + '\\downloadProducts.sh' + ' ' + promObj.requestURLS[i] + ' ' + promObj.Name[i], function (error, stdout, stderr) {
if (error != null){
console.log(error);
}
// this task is resolved
return callback(error, stdout);
});
}, function (err) {
if (err) console.log('error')
else {
console.log('Done');
}
});
}
What have I missed? Thanks in advance.
exec is asynchronous, it does not wait for the launched process to finish.
Move the call to callback() inside the child.on('exit' ...) handler or use execSync
I trying to pass some of the arguments to the child process in node js. I'am actually running a phantom script inside the child process.I'am using execFile method to run my child script. This is how my index.js looks:
var childProcess = require('child_process');
var path = require('path');
var phantomjs = require('phantomjs');
var binPath = phantomjs.path
console.log('inside index method ');
// Set the path as described here: https://aws.amazon.com/blogs/compute/running-executables-in-aws-lambda/
// Set the path to the phantomjs binary
//var phantomPath = path.join(__dirname, 'phantomjs_linux-x86_64');
// Arguments for the phantom script
var processArgs = [
path.join(__dirname, 'ThumbnailCreator.js'),
'myargs'
];
// Launch the child process
childProcess.execFile(binPath, processArgs, function(error, stdout, stderr) {
console.log('stdout: ', stdout);
console.log('stderr: ', stderr);
if (error !== null) {
console.log('exec error: ', error);
}
});
And m trying to print the argument which i have passed.But it is not printing anything. This is how m trying to print it in the child process:
console.log(process.argv[1]);
You can parse it like this in ThumbnailCreator.js
var system = require('system');
var args = system.args;
args[0] is file name
args[1] will give you value passed in first argument.
I'm trying to work with Child Spawn (not working) instead of Exec (working). My Exec code provides me with console output, I see nothing if I run my child spawn code, how can I get console output using Child Spawn:
Here is my working exec code:
var exec = require('child_process').exec,
child;
child = exec('myProgram --version', {},
function (error, stdout, stderr) {
console.log('stdout: ' + stdout);
console.log('stderr: ' + stderr);
if (error !== null) {
console.log('exec error: ' + error);
}
});
child.stdout.on('data', function(data) {
console.log(data.toString());
});
child.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
Here is my non-working attempt at using spawn:
var spawn = require('child_process').spawn;
var spawnchild = spawn('myProgram', ['--version']);
spawnchild.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
spawnchild.stderr.on('data', function(data) {
console.log('stdout: ' + data);
});
If you add a 'close' event handler for spawnchild, you will see a non-zero exit code. The reason for this is that the first argument for spawn() differs from that of exec(). exec() takes the full command line string, whereas spawn() has just the program name/path for the first argument and the second argument is an array of command line arguments passed to that program.
So in your particular case, you'd use:
var spawnchild = spawn('myProgram', ['--version']);
I'm using exec() in node webkit to open a file in the operating system's default program using start filename after it saves the file. Here is my code:
var fs = require('fs');
var myFile = "C:/TEMP/" + fileName;
fs.writeFile(myFile, rtf, function(err) {
if(err) {
alert("error");
}
});
var sys = require('sys');
var exec = require('child_process').exec;
var child;
child = exec("start " + myFile, function (error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
}
});
Sometimes it works, but sometimes I'm getting this error: exec error: Error: Command failed: The process cannot access the file because it is being used by another process.
Edit: I saw that Microsoft has this issue with rtf and txt documents opening in wordpad (which is what mine was being opened in), so I thought it might have been that process hanging up and not dying properly. Before I called it quits for the night, I changed the default program to open in Libre Office and had better results (it didn't happen as often), but if I tried to fire the function quickly in sequence, I would still get the error.
writeFile is async. You need a callback like this:
var fs = require('fs');
var myFile = "C:/TEMP/" + fileName;
fs.writeFile(myFile, rtf, function(err) {
if(err) {
alert("error");
}else{
lire();
});
var sys = require('sys');
var exec = require('child_process').exec;
var child;
function lire(){
child = exec("start " + myFile, function (error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
}
});
};
I am working through smashing node.js - the first book example shows a function that brings in all the current directory files into a list, then file(i) is run, without it being called. I don't know why? - the input parameter to the function is used within the program and incremented as well, but where does this value come from? How is this function called in the first place?
/**
* Module dependencies.
*/
var fs = require('fs')
, stdin = process.stdin
, stdout = process.stdout
/**
* Read the current directory.
*/
fs.readdir(__dirname, function (err, files) {
console.log('');
if (!files.length) {
return console.log(' \033[31m No files to show!\033[39m\n');
}
console.log(' Select which file or directory you want to see\n');
// called for each file walked in the directory
var stats = {};
function file(i) {
var filename = files[i];
fs.stat(__dirname + '/' + filename, function (err, stat) {
stats[i] = stat;
if (stat.isDirectory()) {
console.log(' '+i+' \033[36m' + filename + '/\033[39m');
} else {
console.log(' '+i+' \033[90m' + filename + '\033[39m');
}
if (++i == files.length) {
read();
} else {
file(i);
}
});
}
// read user input when files are shown
function read () {
console.log('');
stdout.write(' \033[33mEnter your choice: \033[39m');
stdin.resume();
stdin.setEncoding('utf8');
stdin.on('data', option);
}
// called with the option supplied by the user
function option (data) {
var filename = files[Number(data)];
if (!filename) {
stdout.write(' \033[31mEnter your choice: \033[39m');
} else {
stdin.pause();
if (stats[Number(data)].isDirectory()) {
fs.readdir(__dirname + '/' + filename, function (err, files) {
console.log('');
console.log(' (' + files.length + ' files)');
files.forEach(function (file) {
console.log(' - ' + file);
});
console.log('');
});
} else {
fs.readFile(__dirname + '/' + filename, 'utf8', function (err, data) {
console.log('');
console.log('\033[90m' + data.replace(/(.*)/g, ' $1') + '\033[39m');
});
}
}
}
// start by walking the first file
file(0);
});
I must be misunderstanding your question... cuz it seems to straightforward.
The line at the bottom:
// start by walking the first file
file(0);
Is the line the "kicks-off" the file(i) chain. That line is at the bottom of the callback of the fs.readdir and is called when it gets to that point after defining the other functions and variables in the main body of the fs.readdir callback.
Am I missing something to your question?