I am working on my class project in which I want to demonstrate the use of mongoDB sharding. I am using mongoDB node.js native driver. I got to know there is no sharding functionality in this driver. So, I have to write shell script to do sharding. So, Is it possible to do this somehow like this:
node myfile.js (executes my shell script and run my code)
Given that you already have a shell script, why not execute that through the Child Process module. Just use the below function to run the script that you have.
child_process.execFileSync(file[, args][, options])
Note that the script should have run permissions(use chmod a+x script otherwise)
why don't you consider using npm run scripts?
if you want the script to run standalone, add scripts with test/start or both to your package json,
"scripts": {
"test": "node mytestfile.js",
"start": "node ./myfile --param1 --param2"
},
and run npm run test or npm run start which can execute the script file. this way you can even pass parameters to the script.
or the elegant child_process way,
const { exec } = require("child_process");
exec("node myfile.js", (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
stderr and stdout will show the progress of the script as you build further.
hope this helps.
Related
I am trying to run MacOS shortcuts via NodeJS script. To achieve that I created shortcuts in the MacOS Shortcuts app, which normally run in the terminal (ZSH) by typing shortcuts run shortcutname (Docs). They work fine when typing them directly into the terminal, but not when called from a NodeJS script.
My script looks like this:
exec('shortcuts run shortcutname', (error, stdout, stderr) => {
if (error) {
console.log(`error: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr: ${stderr}`);
return;
}
console.log(`stdout: ${stdout}`);
});
When starting the script from the terminal node script.js it does nothing. It does not return anything nor does it finish. I tried replacing the command shortcuts run shortcutname by other commands the system should know. For example ls, or git. They all work. Also when I leave out the shortcutname in the end, it complains about the missing parameter.
I was suspecting missing access rights, but apparently NodeJS runs as my normal user. Running whoami in script context returns my user name.
NODE_DEBUG=cluster,net,http,fs,tls,module,timers node script.js did not show anything unusual. I also tried using the full path of the binary. which shortcuts gave me /usr/bin/shortcuts. Which I used in my script /usr/bin/shortcuts run shortcutname.
What am I missing? Thanks in advance!
Though I thought I tested it, I found the solution:
execSync instead of exec works
It’d be cool if someone could explain why exec wouldn’t work.
Cheers!
In the package.json file, I have a line in the scripts object like this:
"scripts": {
// some commands..
"runpackage": "someNpmPackage -args"
}
This someNpmPackage is a package I have in my node_modules, but not in the command line. (i.e. I can run the command in the terminal).
This works fine. However, I want to be able to do in the scripts: "runPackage": "node scripts/runPackage.js"
I try something like
var exec = require('child_process').exec;
exec('someNpmPackage -args', function (err) {
if (err) {
console.log(err.message);
process.exit();
}
console.log('success');
});
But all I get is, /bin/sh: someNpmPackage: command not found.
How can I make the exec function know about this package?
Why don't you install the someNpmPackage globally in your system?
Try in the root project folder, on the command line: ./node_module/.bin/someNpmPackage. If this command works, then it should work with exec.
If I try to run my sequelize migrations and then run my Node server in the same command, I run into the issue of my server never starting up. If the migrations have already been run before, the sequelize db:migrate command doesn't go past the "No migrations were executed, database schema was already up to date." message, and my second command is never able to run. If the migration has not run before, everything runs properly in sequence.
This is my npm start command: sequelize db:migrate && node index.js
I assume that internally sequelize db:migrate is not resolving anything in the case where this log message is shown, so is there a way I can "terminate" this command after some time and proceed to my node command?
For anyone else running into this issue, this is how I ended up solving it.
1) Create a new file that you will run in your npm script.
2) I ended up wrapping the process call in a child_process exec, and then terminated the process when I received the above console.log message since the library itself does not resolve anything at this point.
// myRuntimeFile.js --> Make sure this file is in the same directory where your .sequelizerc file lives
(async()=> {
const { exec } = require('child_process');
await new Promise((resolve, reject) => {
const migrate = exec(
'sequelize db:migrate',
{ env: process.env },
(err, stdout, stderr) => {
resolve();
}
);
// Listen for the console.log message and kill the process to proceed to the next step in the npm script
migrate.stdout.on('data', (data) => {
console.log(data);
if (data.indexOf('No migrations were executed, database schema was already up to date.') !== -1) {
migrate.kill();
}
});
});
})();
Obviously the above code is not ideal, but hopefully this is just temporary until the internals of this edge case are resolved properly in a promise.
3) Update your npm script with the following:
"start": "node myRuntimeFile.js && node index.js"
Or if you are running on a Windows machine and cannot use &&, you can use the npm-run-all library.
This may sound rather crazy,
but I cannot find a solution to automate taking screenshots on a cordova application.
I know I can take and save a screenshot of the emulator using
adb shell /system/bin/screencap -p /sdcard/screenshot.png
adb pull /sdcard/screenshot.png screenshot.png
in the terminal, my crazy question is.
Can I trigger these commands from a nodeJS automation script? or is this too far fetched and a terrible idea?
Simplest way to execute terminal commands from node.js would be to use child_process.exec
const exec = require('child_process').exec;
exec('adb shell /system/bin/screencap -p /sdcard/screenshot.png', (error, stdout, stderr) => {
if (error) {
console.error(`exec error: ${error}`);
return;
}
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
});
The built-in child_process module in node.js provides many functions such child_process.spawn, child_process.exec, child_process.execFile which can be used to execute terminal commands or other script files (.sh, .bat).
I'm neewbe in writing node.js command line scripts. In my project we have a multi-app environment. To setup a dev env we need to launch 2 or more apps, so I'm wondering if it's possible to write a script which will do the following :
run a webpack --watch for my common project which will generate a bundle files
propagate bundles to the other apps.
launch webpack-dev-servers for others apps in separate terminals.
Is it possible to do that from a node script? At this moment I only achieved to implement the second step - a file propagation.
You can spawn a child process with node easily. So you could start multiple child processes from one file.
const exec = require('child_process').exec;
const child = exec('webpack --watch',
(error, stdout, stderr) => {
console.log(`stdout: ${stdout}`);
console.log(`stderr: ${stderr}`);
if (error !== null) {
console.log(`exec error: ${error}`);
}
});
Check the corresponding docs: https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback