Node child_process.spawn multiple commands Node child_process.spawn multiple commands node.js node.js

Node child_process.spawn multiple commands


From Node.js v6 you can specify a shell option in spawn method which will run command using shell and thus it is possible to chain commands using spawn method.

For example this:

var spawn = require('child_process').spawn;var child = spawn('ls && ls && ls', {  shell: true});child.stderr.on('data', function (data) {  console.error("STDERR:", data.toString());});child.stdout.on('data', function (data) {  console.log("STDOUT:", data.toString());});child.on('exit', function (exitCode) {  console.log("Child exited with code: " + exitCode);});

Will trigger an error on node.js version less than 6:

Error: spawn ls && ls && ls ENOENT

But on version 6 and higher it will return expected result:

node app.jsSTDOUT: app.jsSTDOUT: app.jsapp.jsChild exited with code: 0


The | symbol on the command line is called "piping" because it's like piping streams of data together. What you want is to get ahold of the stdin (Standard In) and stdout (Standard Out) streams for the commands you're executing.

For example, this is how you would spawn the echo command and pipe it's output to grep:

var spawn = require('child_process').spawn;var echo = spawn('echo', ['The quick brown fox\njumped over the lazy dog.']);var grep = spawn('grep', ['brown']);echo.stdout.pipe(grep.stdin);grep.stdout.pipe(process.stdin);

The above example spawns both the "echo" and "grep" commands. It pipes any output from the echo process's stdout stream to the grep process's stdin stream. Finally we pipe the grep process's stdout stream to the parent process's (your node process) stdin stream so you can see the output in your terminal.

The output would be "The quick brown fox" because I put a newline character in the middle and the grep only matched the first line containing "brown".

You could use the exec function to achieve the same result. Just might be harder to maintain in the future, but if all you need is to quickly run a set of piped commands, you can enter the full command line string (including pipe symbols) and pass it to exec.

var exec = require('child_process').exec;var cmdString = 'grep "The quick brown fox\njumped over the lazy dog." | grep "brown"';exec(cmdString, (err, stdout, stderr) => {  console.log(stdout);});

Or instead of passing in the callback function you could just pipe the output to process.stdin if all you care about is seeing the command output.

exec(cmdString).stdout.pipe(process.stdin);

Here's a quick example of what I believe your code should look like using spawn. May require tweaks since it seems specific to what you're doing.

var keyArgs = [  '-exportcert',  '-storepass','mypass',  '-keypass','mypass',  '-alias','myalias',  '-keystore',"myjey.keystore",  'openssl','sha1',  '-binary',  'openssl','base64',];var keyOpts = {  cwd: `${appCreateFolder}/${opt.id}/Certificates`};var spawn = require('child_process').spawn;var keytool = spawn('keytool', keyArgs, keyOpts);var opensslBinary = spawn('openssl', ['sha1', '-binary']);var opensslBase64 = spawn('openssl', ['base64']);keytool.stdout.pipe(opensslBinary.stdin);opensslBinary.stdout.pipe(opensslBase64.stdin);opensslBase64.stdout.pipe(process.stdin);opensslBase64.on('close', () => {  console.log(chalk.cyan('Key created.'));});

Or using exec:

var exec = require('child_process').exec;var cmdString = 'keytool -exportcert -storepass mypass -keypass mypass -alias myalias -keystore mykey.keystore | openssl sha1 -binary | openssl base64';var cmdOpts = {  cwd: `${appCreateFolder}/${opt.id}/Certificates`};exec(cmdString, cmdOpts, () => {  console.log(chalk.cyan('Key created.'));});