nodejs run a bash script using spawn - node.js

I know this question has been asked many times but I have tried most of the methods and they just don't work for me.
So here is my problem, I have a simple bash script like this
#!/bin/bash
echo "Username: $1";
echo %DATABASE_URL%;
I want to run this script in a separate process. so if the parent process gets killed during my script being excused it still continues running.
Here is my nodejs code
const child = spawn('bash', [`script.sh`, 'test'], {
detached: true,
cwd: process.cwd(),
detached: true,
stdio: "inherit",
DATABASE_URL: 'test'
}, function (err, stdout, stderr) {
// Node.js does not invoke this
console.log(stdout);
stdout.on("data", data => {
console.log('Output of script execution');
});
stderr.on("data", data => {
console.log('an error with file system');
});
});
child.unref();
child.on('exit', (code) => {
console.log("Child exited");
});
So I know that my script returns some output and should run callback but it does not run it. It directly jumps to the on.('exit') callback which confuses me.
Also it worth mentioning that I am testing the code on windows and bash script.sh 'test' works if I run it on cmd.
Posts I have tried:
How to run shell script file using nodejs?
Execute script from Node in a separate process
Bash Script : what does #!/bin/bash mean?
and many of the existing weblogs that explains the same.

Related

Why do nodejs exec/spawn not show any output for bash 'history' command?

I am running this on Ubuntu and have tried many variations of exec/spawn functions (and their sync counterparts) and none of them can show me an output for bash 'history' command. One scenario is following:
const { spawnSync} = require('child_process');
const child = spawnSync('history', { shell: "/bin/bash" });
console.log('error: ', child.error);
console.log('stdout: ', child.stdout.toString());
console.log('stderr: ', child.stderr);
It does not show any errors and output is empty. I think this question has more to do with 'specialty' or category of the history command than nodejs's function since they work fine for normal commands like ls, pwd, whoami, etc work fine. I have looked at my .bash_history file and its filled with history so that's not the issue.
Another problem that might be similar is ll command also fails even though I have set bash as shell. But for ll, it does return an error:
/bin/bash: ll: command not found
Just to be sure, I tried running ll command in bash it worked just fine. What am I missing here?
edit: I have done some more testing it seems more like a bash thing than a node thing. When I simply write the history command, bash prints results but when I do bash -c history, it does not show any output but also no error.
.
You need to subscribe to messages from child process
child.on('error', (err) => {
});
child.stderr.on('data', (data) => {
});
child.on('exit', (code, signal) => {
});

NodeJS, can I spawn a command such as "lerna" with several interactions?

I am trying to simplify my workflow and for that I'd need to run from Node
a script that execute some commands
The ones that are no interactive, such as git add * and so on I can do with require('child_process').exec just fine
But the ones that require the user intervention such as lerna blah I cannot
I've tried something like
let { stdout, stderr } = await spawn('lerna', [lerna_option, '--no-push'], {
env: process.env,
stdio: 'inherit',
shell: true,
})
if (stdout) console.log('\n' + stdout)
if (stderr) console.log('\n' + stderr)
But it gives me one interaction and then goes on, not allowing me to ask all the questions and run as intended
Is there any simple way to accomplish this?

Having trouble running child process command

I am trying to execute a nodejs file called create-MySwitch.js through a child process in my main.js file.
this is the code for main.js
const exec = require('child_process').exec;
var cmdStr = 'node /home/pi/Desktop/lan-device/create-MySwitch.js';
exec(cmdStr,
{argv: {
port:8080,
uuid:'MyThing'
}},
(error, stdout, stderr)=>{
if (error) {
console.error('exec error: ${error}');
console.log(error);
return;
}
console.log('stdout: ${stdout}');
console.log('stderr: ${stderr}');
});
This is how I am attempting to access the arguments in the create-MySwitch.js file
var port_value = process.argv.port;
var uuid_value = process.argv.uuid;
The output is
stdout: ${stdout}
stderr: ${stderr}
when I run the command
node main.js
I do not think it's working because the output from executing the create-MySwitch.js file should be 'ready', but clearly is not being printed in the stdout variable from the child process.
Essentially, what I am trying to do is run the command 'node createMySwitch.js ', but instead of just typing this in to the command prompt I want to run that command using a child process.
I am doing all of this using the raspbian operating system.

How to run shell script file using nodejs?

I need to run a shell script file using nodeJS that executes a set of Cassandra DB commands. Can anybody please help me on this.
inside db.sh file:
create keyspace dummy with replication = {'class':'SimpleStrategy','replication_factor':3}
create table dummy (userhandle text, email text primary key , name text,profilepic)
You could use "child process" module of nodejs to execute any shell commands or scripts with in nodejs. Let me show you with an example, I am running a shell script(hi.sh) with in nodejs.
hi.sh
echo "Hi There!"
node_program.js
const { exec } = require('child_process');
var yourscript = exec('sh hi.sh',
(error, stdout, stderr) => {
console.log(stdout);
console.log(stderr);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
Here, when I run the nodejs file, it will execute the shell file and the output would be:
Run
node node_program.js
output
Hi There!
You can execute any script just by mentioning the shell command or shell script in exec callback.
You can execute any shell command using the shelljs module
const shell = require('shelljs')
shell.exec('./path_to_your_file')
you can go:
var cp = require('child_process');
and then:
cp.exec('./myScript.sh', function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a command in your $SHELL.
Or go
cp.spawn('./myScript.sh', [args], function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a file WITHOUT a shell.
Or go
cp.execFile();
which is the same as cp.exec() but doesn't look in the $PATH.
You can also go
cp.fork('myJS.js', function(err, stdout, stderr) {
// handle err, stdout, stderr
});
to run a javascript file with node.js, but in a child process (for big programs).
EDIT
You might also have to access stdin and stdout with event listeners. e.g.:
var child = cp.spawn('./myScript.sh', [args]);
child.stdout.on('data', function(data) {
// handle stdout as `data`
});
Also, you can use shelljs plugin.
It's easy and it's cross-platform.
Install command:
npm install [-g] shelljs
What is shellJS
ShellJS is a portable (Windows/Linux/OS X) implementation of Unix
shell commands on top of the Node.js API. You can use it to eliminate
your shell script's dependency on Unix while still keeping its
familiar and powerful commands. You can also install it globally so
you can run it from outside Node projects - say goodbye to those
gnarly Bash scripts!
An example of how it works:
var shell = require('shelljs');
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
}
// Copy files to release dir
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');
// Replace macros in each .js file
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
shell.cd('..');
// Run external tool synchronously
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
shell.echo('Error: Git commit failed');
shell.exit(1);
}
Also, you can use from the command line:
$ shx mkdir -p foo
$ shx touch foo/bar.txt
$ shx rm -rf foo

Run block of bash / shell in node's spawn

I'm writing a command line utility, and I need stdout to write to TTY or use {stdio: 'inherit'} I've been getting by with exec but it's not going to cut it. I need way for a spawn process to execute the following echo commands below. I know that spawn spins up a child process with a given command, and you pass in arguments, but I need it to just take a line-separated string of commands like this. This is what I'm currently feeding to exec. Is this possible?
const spawn = require('child_process').spawn
const child = spawn(`
echo "alpha"
echo "beta"
`)
child.stdout.on('data', (data) => {
console.log(`stdout: ${data}`)
});
child.stderr.on('data', (data) => {
console.log(`stderr: ${data}`)
});
child.on('close', (code) => {
console.log(`child process exited with code ${code}`)
});
spawn() does not involve a shell, so in order to have it execute shell commands, you must invoke the shell executable explicitly and pass the shell command(s) as an argument:
const child = spawn('/bin/sh', [ '-c', `
echo "alpha"
echo "beta"
` ])
Note I've used /bin/sh rather than /bin/bash in an effort to make your command run on a wider array of [Unix-like] platforms.
All major POSIX-like shells accept a command string via the -c option.

Resources