Im trying to reduplicate the shelljs exec type execution in node - node.js

I was using shelljs before where i used to call a command like so:
require('shelljs/global');
let res = exec('echo hello').stdout
But I would like to achieve this in node without relying on shelljs.
Thing is I've found examples with node and I'm having trouble with quite a few of them.
Thanks for the help

The ultra simple answer is use the synchronous version of exec. The stdout won't appear as the command runs and the result won't have the nice properties shelljs provides, just the stdout data
const { execSync } = require('child_process')
const exec = (cmd) => execSync(cmd).toString()
const res = exec('echo "hello there"')
The full shelljs implementation is in exec.js, which runs the command via exec-child.js script to enable the live output + capture to variables for a synchronous exec. It depends on the features you require as to how complex the solution becomes.

Related

Executing Command in Nodejs and Attaching the output to the console

I'm working on a CLI tool to add an extra layer of automation and utilities to our workflow and I'm wrapping the webpack development command with an alternative in my CLI (here's a demonstration):-
function runDev(){
this.doSomePreAutomationAndPreperations();
this.runWebpackDevCommand();
}
I'm using NodeJs child_proecess.exec and I'm trying to figure out a way to execute the webpack dev command and attach it to the terminal (like -it in docker if you're familiar with it) or transferring the control to the child process(so output will be directly emitted to the console).
Is there away to do that?
It turns out that I can achieve this but just making the child process inherit the stdio. ex:-
const { spawn } = require('child_process')
const shell = spawn('sh',[], { stdio: 'inherit' })
shell.on('close',(code)=>{console.log('[shell] terminated :',code)})

Is there a way to get complete output from child_process.spawn method in node

I am trying to run ng lint --format json command using node's child_process spawn method. The code looks like below:
const spawn = require('child_process').spawn;
const fs = require('fs-extra');
const jsonLog = fs.createWriteStream('test.json', { flags: 'a' });
const linter = spawn('ng', ['lint', '--format', 'json']);
linter.stdout.pipe(jsonLog);
As you can guess, I am trying to output JSON to a file. The problem I am facing is that I am not getting the complete JSON output. It gets truncated at some point making it an invalid JSON. I think it has to do something with buffer size.
Now most of you will suggest me this:
ng lint --format json > jsonFile.json
I am already aware of it. I want to do it programmatically because I am trying to build a utility for it. Let me know if you have any ideas or solution.

Why would calling a child_process command work with exec but not spawn?

Why would this work:
var exec = require("child_process").exec;
var command = exec("grunt");
But this throws an error:
var spawn = require("child_process").spawn;
var command = spawn("grunt");
The error it throws is Error: spawn ENOENT
At first I thought it might have something to do with the env, but it is exactly the same in both exec and spawn. I think it must somehow have something to do with Grunt, since trying git works in both.
On checking the node docs for spawn I found:
Note that if spawn receives an empty options object, it will result in
spawning the process with an empty environment rather than using
process.env. This due to backwards compatibility issues with a
deprecated API.
The default option for env in exec is null, but for spawn it is process.env. So it is ambiguous if both are getting same env? Can you check this by giving same env explicitly for both.
I got the same problem. It only appears on Windows platform. And finally, I found this issue that helped me out of this stuff.
I followed isaacs suggestion:
The cmd is either "sh" or "cmd" depending on platform, and the arg is
always either /c $cmd or -c $cmd.
child = child_process.spawnShell('util.bat glerp gorp', {options...})
Which would be sugar for:
child = child_process.spawn(isWin ? 'cmd' : 'sh', [isWin?'/c':'-c', arg], options)
Then, I wrote my own simple spawnShell:
var spawn = require('child_process').spawn;
function spawnShell(args,options){
var isWin = (process.platform === 'win32');
args.unshift(isWin ? '/c' : '-c');
return spawn(isWin ? 'cmd' : 'sh', args, options);
}
Although it's a little late, hopefully my answer still can help somebody else in the future.

calling child_process.exec in Node as though it was executed in a specific folder

I'm using the following to execute a CLI command in nodeJS
var cp = require('child_process');
cp.exec('foocommand', callback);
However, the foocommand is executing in the current folder node is running from. How can I make it execute as though it is being invoked from a different folder?
Its in the docs:
var cp = require('child_process');
cp.exec('foocommand', { cwd: 'path/to/dir/' }, callback);
Not a total expert but if its a cli then you want to be able to use stdin witch is not available with process.exec. Maybe you want to see if there is a programable interface for the cli?

Is it possible to run PhantomJS from node.js as a command line argument

I was recently going to test out running phantomJS from python as a commandline argument, I haven't got round to it yet but have seen examples. Because PhantomJS is run from the command line this seems to be possible. The result that PhantomJS would spit out would go straight into a variable.
Before I go down that path, making this work in node.js would actually be more useful for me and it got me thinking, can i just use to node to run PhantomJS as a program gets run from the commandline and store the data result that PhantomJS would normally spit out into a variable?
I would rather not use phantomjs-node because it seems to be using too many tricks.
The reason for all of this is to be able to run PhantomJS at the same time as another action the program takes and use the resulting data its recorded for some other stuff.
Simply put, you can run system command line stuff in python, can I do the same in node.js?
Cheers :)
Edit: I understand that node and phantom use different js environments, that's cool because I just want to run phantom as its own process and catch all that output data into a node.js variable (the data will be a array of a pair, string and floating point.) I don't want to 'drive' with phantom, I will craft the loaded javascript files todo what I want. All I want is phantom output. :)
From NPM: https://npmjs.org/package/phantomjs
var path = require('path')
var childProcess = require('child_process')
var phantomjs = require('phantomjs')
var binPath = phantomjs.path
var childArgs = [
path.join(__dirname, 'phantomjs-script.js'),
'some other argument (passed to phantomjs script)'
]
childProcess.execFile(binPath, childArgs, function(err, stdout, stderr) {
// handle results
})
I suppose you can make a simple script for Node.js to run; in that script phantomjs script will be run as a child process. You can see the working example (and links for some documentation) in this answer. I suppose this discussion might be helpful for you as well.
As an alternative to Donald Derek's answer, you can use the spawn function. It will allow you to read the child process's output as soon as it's produced rather than the output being buffered and returned to you all at once.
You can read more about it here.
An example from the documentation.
var spawn = require('child_process').spawn,
ls = spawn('ls', ['-lh', '/usr']);
ls.stdout.on('data', function (data) {
console.log('stdout: ' + data);
});
ls.stderr.on('data', function (data) {
console.log('stderr: ' + data);
});
ls.on('close', function (code) {
console.log('child process exited with code ' + code);
});

Resources