Chris Schmitz Chris Schmitz - 1 month ago 6
Node.js Question

Odd exec output in node

I'm trying to determine if a java runtime environment is installed on the computer running my node app. Here's the promise I'm starting to build out to determine if it's installed:

FileSystemTools.prototype.checkToSeeIfJavaRuntimeEnvIsAvailable = function (){
return new Promise((resolve, reject) => {
exec('java -version', (error, stdout, stderr) => {
if(error) reject(error)
if(stderr) reject(stderr)

resolve(stdout)
})
})
}


The generator function I'm building out to run this check looks like this so far:

co(function *(){
let jreVersion = yield fst.checkToSeeIfJavaRuntimeEnvIsAvailable()
console.log(jreVersion)
}).catch(error => {
throw new Error(error)
})


When I run this I get no output at all. However, if I resolve all of the arguments returned from the
exec
command:

FileSystemTools.prototype.checkToSeeIfJavaRuntimeEnvIsAvailable = function (){
return new Promise((resolve, reject) => {
exec('java -version', (error, stdout, stderr) => {

// resolving early with everything to see what's going on
resolve({error, stdout, stderr})


if(error) reject(error)
if(stderr) reject(stderr)

resolve(error, stdout, stderr)
})
})
}


I'm seeing that my command is firing successful, but it's returning the result in the standard error, not standard output:

{
error: null,
stdout: '',
stderr: 'java version "1.8.0_101"\nJava(TM) SE Runtime Environment (build 1.8.0_101-b13)\nJava HotSpot(TM) 64-Bit Server VM (build 25.101-b13, mixed mode)\n'
}


I double checked the docs on the
exec
callback
thinking that I got the callback parameters wrong, but they're definitely in the right order:

exec callback parameter order

This raises two questions for me:


  1. Why is my successful output of the command returning in standard error?

  2. If it is returning in standard error, why did my if statement to check for standard error and reject if it is truthy not fire?


Answer

By default, java -version writes its result in standard error only, even though the command is executed successfully. You can confirm that by redirecting the stderr to a file, like this

$ sh -c "java -version 2>/tmp/test"
$ cat /tmp/test
java version "1.8.0_102"
Java(TM) SE Runtime Environment (build 1.8.0_102-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode)

If there was an error, the error parameter in the callback would have been an object, with the error code and the signal.