Nodejs child_process spawn with $ variable - node.js

Question: Can I access $variable via {spawn} = require("child_process") ?
Background: I have already tried using exec("echo $HOME"); which output the correct value.
But when I tried to use spawn("echo",["$HOME"]), I got $HOME
And how to define the variable by using spawn? Currently I'm setting the child_process option {env:{data:1000}}, is this correct or not ?

by default, spawn does not create a shell and then execute the command within that shell (as appose to exec which starts a shell first and then executes the command within that shell).
Since there is no shell, the "$HOME" environment variable is not set. You can set spawn to execute the command within a shell:
spawn("echo",["$HOME", { shell: true });

Related

Expect command does not see stdout when executing with nodejs?

I wrote a bash file with expect command, expecting some output and do actions based on that it works when I execute it in the terminal but when I execute it using exec in nodejs it does not work. I think the output of commands I run in bash file cannot be seen by expect
I usually use, shelljs Package, for executing commands or shell scripts via nodejs.
const shell = require('shelljs')
shell.exec('./path_to_your_file')

Can I access CLI programs from within Node's child_process?

I’ve written a node script that cd’s into multiple directories in sequence and executes bash commands in order to deploy the contents of the repos to my development environment.
Native bash commands work fine, like cd, ls, but it looks like the subshell or child process (or whatever the proper term is, I don’t understand the inner workings of Bash) that’s opened by node doesn’t have anything available to my normal prompt.
E.g.
the custom bash toolset that’s available globally
nvm (is this even possible, to run a different version of node within a node subshell?)
gulp breaks because it doesn't have the necessary node version installed.
Is it possible to access these programs/commands from the node subshell? I’m using the child_process node module.
const { exec } = require('child_process');
function command (command) {
exec (command, (err, stdout, stderr) => {
if (err) {
error(err);
} else {
message(`stdout: ${stdout}`);
message(`stderr: ${stderr}`);
}
});
}
Used as in:
command('nvm use 6');
command('gulp build');
command('pde deploy');
The child process is not run as bash. child_process spawns the executable using the regular sh shell.
If you need the commands to run within bash, the command line you run needs to be wrapped in bash -c. For example:
command('bash -c "my command here"');
Also, each command you run is a sub-process, which does not affect the parent process, nor any subsequent sub processes. Thus, a shell built-in like cd will only change the directory for that sub-process, which immediately goes away. You will see this if you run:
command('cd /');
command('ls');
The ls command will show the current working directory, not the root directory.
If you run your command with bash -c and the $PATH and other environment variables still aren't set up the way you need them, you need to debug your shell start-up scripts. Perhaps there's a difference between interactive shells (.bash_profile) and all shells (.bashrc).
Note that fully non-interactive shells may need to explicitly have the start-up script you want to run specified.

How can I change actual shell cd with nodejs

I am creating a command line program to act as a shortcut for my environment. Commands like $ cd $enterprise/products/<product> are so common, that I like to compile into: $ enterprise product.
My problem is: I cannot change shell directory directly, like running $ cd $enterprise/products/<product> with process.chdir.
Using console.log(process.cwd()) shows that the directory has changed, but not on shell, only on nodejs internal process(I think it's running on a own shell).
Typing $ pwd in shell shows that I still are on the same folder.
I was searching for a solution, like a shell script that interprets the output of a nodejs file, then source the output.
Thanks.
This is actually bit trickier than it sounds.
You can't just change the working directory of the shell that is running the process, without making assumptions about which shell it is or the OS (I personally use applescript to spawn new terminal tabs).
What we can do, however, is spawn a new shell!
let child_process = require('child_process');
child_process.spawn(
// With this variable we know we use the same shell as the one that started this process
process.env.SHELL,
{
// Change the cwd
cwd: `${process.cwd()}/products/${product_id}`,
// This makes this process "take over" the terminal
stdio: 'inherit',
// If you want, you can also add more environment variables here, but you can also remove this line
env: { ...process.env, extra_environment: 'some value' },
},
);
When you run this, it seems like you cd into a directory, but actually you are still running inside nodejs!
You can't do this; every child process has its own working directory inherited from the parent. In this case, your cd gets its working directory from its parent (your shell). A child process can't change the directory – or any other state – of the parent process.

How to access shell variable value from Node.js?

Let's say there is a variable key1 and its value is 123
key1=123
so when I run the command in linux environment echo $key1, I get output as 123.
Now I have the following gulp task.
const child_process = require('child_process');
....
gulp.task('printKeyValue', function() {
var value1 = child_process.execSync('echo $key1');
console.log(value1.toString().trim());
});
Here, I'm trying to access value of linux variable from nodejs by using Child Process
But when I run the following gulp task, I don't get the desired output.
npm run gulp -- printKeyValue
Instead I get output as $key1 and not 123.
See below screenshot
Other commands like ls & pwd in gulp task gives the desired output.
Can some one please help on this or suggest an alternate way?
You are not exporting the variable. When you just do
key1=123
the variable is not propagated to subprocesses. It will be available in your current bash process, so you can see it when you type echo $key1, but it will not get inherited by the node process. As man bash says:
When a simple command other than a builtin or shell function is to be executed, it is invoked in a separate execution environment that consists of the following. Unless otherwise noted, the values are inherited from the shell.
[...]
shell variables and functions marked for export, along with variables exported for the command, passed in the environment
You need to either define the variable as exported
export key1=123
or mark an existing variable for export
key1=123
export key1
or launch your node with the modified environment, either via the bash innate capability to do so
key1=123 node code.js
or using /usr/bin/env utility:
env key1=123 node code.js
Once the variable is properly passed to the node process, it will be available both in process.env.key1 and as $key1 in a child process.
EDIT: I just noticed, you actually gave the command you're running; it does not matter, the same logic goes for every executable, whether node or npm or anything else.

Need to call function written inside a shell script from node js

I need to call a function written inside a shell script from node js. I have tried the command "source test.sh a" , where 'a' is the method inside test.sh in shell command. It works but from nodejs how to call it using execFile/spawn.
With child_process spawn, you could do it with the { shell: true } option (to spawn a shell), but it seems that the exec method is more appropriate in this case:
const { exec } = require('child_process');
exec('source ./test.sh && a');

Resources