0

In our environment, we're building a build/util tool to be used by many users without the need for external (or system-wide) dependencies. Namely, we're attempting to build this so that users won't have to be concerned with which version of node.js they have installed globally, as we're packing the node.js binary within the tool directory. (Please refrain from commenting on the merits of such an approach).

Our tool structure is as such:

/web/tool/
/web/tool/bin/ (where the node binary lives)
/web/tool/node_modules

We have /web/tool/bin added to the $PATH variable (first in order) upon execution of any of the scripts or grunt.js tasks to ensure that the local binaries path trumps any other.

Upon execution of any bash scripts or grunt.js tasks, the initial task locates the proper node binary. This was tested in an environment without node installed globally, so we knew it was finding the directory-local node binary. Any subsequent processes spawned from within these scripts/grunt-tasks however, are looking globally for the node binary.

Our specific user-case is running karma and phantomjs via a grunt task. The bash scripts/bins for karma, grunt-cli (grunt), and phantomjs all have the familiar header directive of

#!/usr/bin/env node

How should we go about setting up so that our tool is always looking for the directory-local node binary, even in subsequent child-processes?

shellscape
  • 840
  • 1
  • 6
  • 17
  • Could you write a wrapper script that finds the `node` binary and does something like `export NODE=/web/tool/bin/node` to set the environment variable to the local NodeJS binary before kicking off your actual script? – Michael Tang Dec 19 '13 at 18:08
  • Why does subsequent processes has to look globally for node, if you have the pathname for the binary of node you want to execute the first process? Also it sounds like virtualenv for nodejs, so have you tried http://stackoverflow.com/questions/3653495/is-there-an-virtual-environment-for-node-js? – leorex Dec 19 '13 at 20:34
  • @MichaelTang that's the crux of the problem. We can change the envars temporarily for a command, but the subsequent child proccesses don't see to pick up on it. – shellscape Dec 19 '13 at 22:06
  • @leorex thanks for pointing me there, I'll investigate nodeenv and see if that solves our problem. the child processes are spawned inside of node modules which we don't control (karma, phantomjs) so it's problematic. – shellscape Dec 19 '13 at 22:07
  • If you're starting the child scripts with [`child_process`](http://nodejs.org/api/child_process.html), you can pass an appended `process.env` as the `env` object option. – Michael Tang Dec 19 '13 at 23:51
  • @MichaelTang that would require manually editing the source of the modules the processes are started in (karma, phantomjs) putting them out of sync. We're pursuing pull requests to allow for that in the respective projects but we're trying to avoid getting out of sync. – shellscape Dec 20 '13 at 03:35

1 Answers1

0

Definitely try creating a wrapper script to set environment variables to pass on to child classes:

node ./wrapper.js (you write/execute this one)

#!/usr/bin/env node

console.log(process.env.NODE); // "/usr/local/bin/node"

process.env.NODE = "/web/tool/bin/node";

require('child_process').exec('node ./child.js', {
    'cwd': __dirname,
    'env': process.env
}, function(err, stdout, stderr) {
    console.log('stdout: ' + stdout);
    console.log('stderr: ' + stderr);
    if (err !== null) {
        console.log('exec error: ' + error);
    }
});

child.js (or whatever other script you have, note that it does not need to be modified)

#!/usr/bin/env node

console.log(process.env.NODE);

Output:

$ node env.js
/usr/local/bin/node
stdout: /web/tool/bin/node (from child.js)

stderr:
Michael Tang
  • 4,686
  • 5
  • 25
  • 24
  • Marking this as the answer, as it addressed the original question. We've gone with a different solution though, and implemented nodeenv ekalinin.github.io/nodeenv/ which has solved all of our extended concerns. – shellscape Jan 09 '14 at 17:04