Unable to spawn a custom .exe from express.js on Windows - node.js

I am using node.js/express.js on windows and I have a command I execute when a user takes a image and uploads up from there phone. Once it is uploaded I run myApp.exe to perform some openCV image processing and I output the updated images to a output directory that is a argument in the command below.
I am able to kick this off from my webapp using child_process.exec, but the performance is 60x slower if I run it at command line by itself. To increase the performance I was hoping to use Spawn, but I don't know if this is an accurate assumption, please let me know if it is not.
var exec = require('child_process').exec;
var child = exec('C:\\opt\\package_v030_package\\myApp.exe
--user="C:\\opt\\package_v030_package\\Phone\\'+file.filename+'"
--mv="C:\\opt\\package_v030_package\\mv\\'+req.body.detectionString+'.bmp"
--outPath="C:\\opt\\package_v030_package\\output"
--outputScaled
--outputScaledOverlaid');
child.stdout.on('data', function(data) {
console.log('stdout: ' + data);
});
child.stderr.on('data', function(data) {
console.log('stdout: ' + data);
});
child.on('close', function(code) {
console.log('closing code: ' + code);
//res.json("success")
});
I have tried to kick it off using spawn, but it fails to execute with the following: "error child process exited with code 4294967295". The code is below:
var spawn = require('child_process').spawn;
var cmd = spawn('cmd', ['/s',
'/c',
'C:\\opt\\package_v030_package\\myApp.exe',
'--user="C:\\opt\\package_v030_package\\Phone\\'+file.filename+'"',
'--mv="C:\\opt\\package_v030_package\\mv\\'+req.body.detectionString+'.bmp"',
'--outPath="C:\\opt\\package_v030_package\\output"',
'--outputScaled',
'--outputScaledOverlaid'
]);
cmd.stdout.on('data', (data) => {
console.log(`stdout: ${data}`);
});
cmd.stderr.on('data', (data) => {
console.log(`stderr: ${data}`);
});
cmd.on('close', (code) => {
console.log(`child process exited with code ${code}`);
});
It seems I am able to execute just myApp.exe from spawn because when I add any of my arguments it fails. Even when I hard code the variables that I inject. Is there an issue with my arguments or am I spawning myApp.exe incorrectly?
Update 1
I placed the command in a .bat and was able to execute it from node.js using spawn. It does not increase performance which leads me to believe that the decrease in performance is a limitation of node.js on the windows platform.
In addition, I performed a few tests using postman to see if I could optimize the call without anything else happening, but I did not succeed. I will leave this question open in the event this changes and node.js is able to better handle performance of a CPU intensive child process.
Update 2 & Answer
I was able to fix this by placing the command that we run at the command line into a java class taking in the detectionString as a parameter. Then from node I use spawn to kick off the .jar file. This caused the speed to increase significantly and run as if I was running it myself at command line.

I was able to fix this by placing the command that we run at the command line into a java class taking in the detectionString as a parameter. Then from node I use spawn to kick off the .jar file. This caused the speed to increase significantly and run as if I was running it myself at command line.

Related

Node's spawn/exec not working when called from a scheduled Windows task

I'm facing a very odd issue where I have a Node script which invokes a process, it looks like this:
// wslPath declared here (it's a shell file)
const proc = cp.spawn('ubuntu.exe', ['run', wslPath]);
let stdout = '';
proc.stdout.on('data', data => stdout += data.toString());
let stderr = '';
proc.stderr.on('data', data => stderr += data.toString());
return await new Promise((resolve, reject) => {
proc.on('exit', async code => {
await fs.remove(winPath);
if (code) {
reject({ code, stdout, stderr });
}
resolve({ stdout, stderr });
});
});
As you can see, the script invokes WSL. WSL is enabled on the computer. When I run this script manually, it works fine. When I log in to the computer the script is at using RDP from another computer and run it with the same credentials, it works fine as well. But when the script is invoked from a scheduled task which also runs with the same credentials, the spawn call returns:
(node:4684) UnhandledPromiseRejectionWarning: Error: spawn UNKNOWN
at ChildProcess.spawn (internal/child_process.js:394:11)
at Object.spawn (child_process.js:540:9)
I verified the user is the same by logging require('os').userInfo() and require('child_process').spawnSync('whoami', { encoding: 'utf8' }) and it returns the same in all three cases.
I assume it is because ubuntu.exe is not being found, but I don't know why that would be as the user is the same in all three cases.
What could be the reason for this and how can I debug this further?
The Windows Task Scheduler allows you to specify a user to run as (for privilege reasons), but does not give you the environment (PATH and other environment variables) that are configured for that user.
So, when running programs from the Windows Task Scheduler, it's important to not make any assumptions about what's in the environment (particularly the PATH). If my program depends on certain things in the environment, I will sometimes change my Task to be a .BAT file that first sets up the environment as needed and then launch my program from there.
Among other things, the simplest way to not rely on the path is to specify the full path to the executable you are running rather than assuming it will be found in the path somewhere. But, you also need to make sure that your executable can find any other resources it might need without any environment variables or you need to configure those environment variables for it before running.

NodeJS child process stdout not returning completly

I'm running the following code using node and I always get only about 80% of what stdout is supposed to return when the file is past 12ko or so. If the file is 240ko it will still output 80% of it. If it's under 12 it will output completely.
When I open a cmd and run the command manually I always get the full output.
I tried exec, execFile, I tried increasing the max buffer or changing the encoding and it's not the issue. I tried to add options {shell: true, detached: true} but it vain, in fact, when I run it as detached it seems to be running completely fine as it does open an actual console but I'm not able to retrieve the stdout when the process is completed.
const spawn = require('child_process').spawn;
const process = spawn(
'C:\\Users\\jeanphilipped\\Desktop\\unrtf\\test\\unrtf.exe',
['--html' ,'C:\\Users\\jeanphilipped\\Desktop\\unrtf\\test\\tempaf45.rtf'],
);
let chunks = [];
process.stdout.on('data', function (msg) {
chunks = [...chunks, ...msg];
});
process.on('exit', function (msg) {
const buffer = Buffer.from(chunks);
console.log(buffer.toString());
});
Any clues ? It seems to be Node since when I run it manually everything works fine.
according to nodejs documentation, all of the child_process commands are asynchronous . so when you try to access your chunk variable there is no guarantee that you command has been finished , maybe your command is still on process. so it is recommended you should wrap your entire child_process command in async/await function.

How to REALLY kill a child_process nodejs

I'm using mocha with Nodejs to test my restApi.
When I run mocha, I tell my test to create a child_process and run the API so I can make requests to it.
The problem is whenever the test exits (finishing or crashing), it seems that the API keeps running on background. I've seen some answers here that instructs to manually kill the child process whenever the main process exits. So I did it like this:
export function startProcess(done) {
const child = spawn('babel-node', ["app.js"]);
child.stdout.on("data", function(data) {
data = data.toString();
// console.log(data.toString());
if(data.indexOf("Server online") > -1) done();
});
child.stderr.on('data', function(err) {
console.log("ERROR: ", err.toString());
});
child.on('exit', function(code) {
console.log("PROPERLY EXITING");
console.log("Child process exited with code", code);
});
process.on('exit', function(code) {
console.log("Killing child process");
child.kill();
console.log("Main process exited with code", code);
});
}
When the main process exits it does log "Killing child process", meaning that child.kill() was indeed called. But if I try to run my test again, when the spawn command gets called, the API throws an error
Error: listen EADDRINUSE :::3300
, meaning that the API is still running and that port address is taken.
So I have to run sudo pkill node to really kill all node process and then npm test works again.
Am I missing something? Is this really the way to achieve what I'm expecting?
I thought about using child_process.exec to run sudo pkill node on my process.on('exit') listener, but that doesnt seem like a smart thing to do.
This is happening both in Mac and Ubuntu.
Any suggestions?
Thanks
"exit" is an event that gets triggered when node finishes it's event loop internally, it's not triggered when you terminate the process externally.
What you're looking for is executing something on a SIGINT.
Have a look at http://nodejs.org/api/process.html#process_signal_events

Assistance with Node.js functions integration in Apache Linux

Here is a short overview to help you experts understand the situation I am in - sorry that its too verbose, but it might help resolving this issue:
So I have a Linux machine, and it runs Apache properly.
Under '/var/www/html', I put my project files which are HTML (index.html) , and a javaScript file with utility functions.
httpd runs and everyone can view the content when 'http:///index.html' from their PC's.
I want to run a bash script from my Linux machine by letting the users provide the parameters from the front end user interface.
Reading how to do that, I saw tons of examples of how node.js can do that, so I downloaded Node.JS to my Linux machine, and it can be run from:
"
~/Desktop/node-v4.2.1-linux-x64/bin/node --version
v4.2.1
~/Desktop/node-v4.2.1-linux-x64/bin/npm --version
2.14.7
"
So it seems like its properly installed...
Note: I did not put anything in my Linux path after extracting the node.js tar.gz file.
Now, from my Linux machine, under '/var/www/html' , I have an HTML file, and I created an 'onclick' event to invoke a javascript function, in which I wrote a call to run this bash script which is located in my Linux machine under "/" - here it is:
function start_run(pTopoFile, pEmailAddress) {
var childProcess = require('child_process');
var run_command;
run_command = childProcess.exec('/run.sh ' + pTopoFile + ' ' + pEmailAddress, function (error, stdout, stderr) {
if (error) {
console.log(error.stack);
console.log('Error code: '+error.code);
console.log('Signal received: '+error.signal);
}
console.log('Child Process STDOUT: '+stdout);
console.log('Child Process STDERR: '+stderr);
});
ls.on('exit', function (code) {
console.log('Child process exited with exit code '+code);
});
}
When I run the above I get this error:
"ReferenceError: require is not defined"
Which means that even though Node.js was installed properly (as I showed you above), I cannot access its methods from /var/www/html on my Linux machine ...
Can anyone let me know how to link between the great features that node.js has to my scripts?
I hope that I was clear enough with the info I provided...
Thanks,
Tom

Is it possible to run PhantomJS from node.js as a command line argument

I was recently going to test out running phantomJS from python as a commandline argument, I haven't got round to it yet but have seen examples. Because PhantomJS is run from the command line this seems to be possible. The result that PhantomJS would spit out would go straight into a variable.
Before I go down that path, making this work in node.js would actually be more useful for me and it got me thinking, can i just use to node to run PhantomJS as a program gets run from the commandline and store the data result that PhantomJS would normally spit out into a variable?
I would rather not use phantomjs-node because it seems to be using too many tricks.
The reason for all of this is to be able to run PhantomJS at the same time as another action the program takes and use the resulting data its recorded for some other stuff.
Simply put, you can run system command line stuff in python, can I do the same in node.js?
Cheers :)
Edit: I understand that node and phantom use different js environments, that's cool because I just want to run phantom as its own process and catch all that output data into a node.js variable (the data will be a array of a pair, string and floating point.) I don't want to 'drive' with phantom, I will craft the loaded javascript files todo what I want. All I want is phantom output. :)
From NPM: https://npmjs.org/package/phantomjs
var path = require('path')
var childProcess = require('child_process')
var phantomjs = require('phantomjs')
var binPath = phantomjs.path
var childArgs = [
path.join(__dirname, 'phantomjs-script.js'),
'some other argument (passed to phantomjs script)'
]
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
// handle results
})
I suppose you can make a simple script for Node.js to run; in that script phantomjs script will be run as a child process. You can see the working example (and links for some documentation) in this answer. I suppose this discussion might be helpful for you as well.
As an alternative to Donald Derek's answer, you can use the spawn function. It will allow you to read the child process's output as soon as it's produced rather than the output being buffered and returned to you all at once.
You can read more about it here.
An example from the documentation.
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});

Resources