Even today, a lot of developers think of JavaScript as something limited to the browser - made popular by hype. I was one of them till a few years ago. But over the past few years, I was pleasantly surprised at the kind of functionality packed into NodeJS. Now I prefer JavaScript for almost all my AWS Lambda Functions.
The turning point was when I had to invoke a shell commend from the JavaScript code. The first thought in my mind was - this can never work! But then, I thought I might just try to Google around. And I was surprised to see several different ways of doing this!
This is how I did it.
Child Process
The child_process is one way to do this. We can use two types of functions: exec() and execFile() to run a command in the base shell.
const { exec, execFile } = require('child_process');
exec('ls -l', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
execFile('ls -l', (err, stdout, stderr) => {
if (err) {
console.error(err);
return;
}
console.log(stdout);
});
Difference between using child_process.exec() and child_process.execFile() in that the latter won't spawn a shell whereas the former will. Unfortunately, windows does not allow execFile() - because we cannot run without a separate terminal. So we have to use exec().
Promisify
One problem with the these methods is that they don't provide a promise(). This can mess up our code. Fortunately, NodeJS provides us the simple promisify() utility that can help us here.
const util = require('util');
const execFile = util.promisify(require('child_process').execFile);
async function getVersion() {
const { stdout } = await execFile('node', ['--version']);
console.log(stdout);
}
getVersion();
Naturally, if we run this on the prompt, it will give an error that await should be run in an async function. But if we do, this returns the node version as expected.
- A simple command that can save the day.