hackjutsu
hackjutsu

Reputation: 8922

Sourcing a shell script from JS

Imagine we have a env.sh with following content.

export SOME_VAL="abcd"

We want to source this shell script from a JS (node.js) script bootstrap.js.

const childProcess = require('child_process');
const cmd = '. ' + pathToEnvScript;
childProcess.exec(cmd, (err, stdout, stderr) => {
    if (err) console.error(err);
    console.log(stdout);
})

Here is how we call the bootstrap.js.

echo $SOME_VAL # empty
node bootstrap.js
echo $SOME_VAL # empty

Why the sourcing doesn't take any effect? The sourcing works if we call source env.sh from terminal, but doesn't work for node bootstrap.js.

Upvotes: 1

Views: 970

Answers (3)

RaphaMex
RaphaMex

Reputation: 2839

Given that

a child process cannot modify its parent env (unless you hack your shell)

the best you can do is

make nodejs tell your shell what to do to update its environment as it would have if it had sourced the script itself.

I assume you are only interested in variables and not functions.

Here is your solution.

bootstrap.js:

const childProcess = require('child_process');
const script = process.argv[2];
childProcess.exec("env > ./1.txt; . ./"+script+" >/dev/null 2>&1; env > ./2.txt; diff 1.txt 2.txt | grep '^>'", (err, stdout, stderr) => {
    stdout.split('\n').forEach((line) => console.log(line.substr(2)));
})

and how you should call it:

echo $SOME_VAL # empty
eval `node bootstrap.js ./file.sh`
echo $SOME_VAL # abcd

Upvotes: 1

Dan O
Dan O

Reputation: 6090

this is not working for at least two reasons. source is a Bash internal command, and node spawns /bin/sh by default. And even if you told child_process.exec to spawn a Bash shell:

child_process.exec("ls", { shell: "/bin/bash" }, (err, stdout) => ())

then the source'd variables would be added to the environment of the shell process, not the environment of node.js .

I don't know what the exact specific requirements are for your project but your best bet might be to open the file in node and parse its contents to find key/value pairs and set node's environment that way.

Upvotes: 0

AuxTaco
AuxTaco

Reputation: 5171

childProcess.exec(command) spawns a shell then executes the command within that shell. Using export makes variables available to child processes of the shell, but not to its parent. Node and the shell from which you invoke Node never see the variable.

Upvotes: 0

Related Questions