Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

nodejs spawn command with string not array?

Tags:

node.js

I'm working on spawn on nodejs. previously I was using exec but exec has no compatibility in stdout (or stderr) steaming. now, I have a disability about spawn. It seems whereas exec accepted quoted string command, spawn does not accepted that one, just array format.

so following exec script is working correctly but another one which uses spawn will be error, due to string formatted command not array.

const exec = require('child_process').exec;

exec(` echo foo bar `, (error, stdout, stderr) => {
  if ( error ){ console.log(error) }
  if ( stdout ){ console.log(stdout) }
  if ( stderr ){ console.log(stderr) }
});
const { spawn } = require('child_process');

command = spawn('echo foo bar');

command.stdout.on('data', function (data) {
  console.log(data.toString());
});

command.stderr.on('data', function (data) {
  console.log( data.toString());
});

command.on('exit', function (code) {
  console.log( code.toString());
});

I have a lot of command line script which is what I want to spawn on nodejs, and all of them are complicated, something like following one. that's why I want to use string format for specify command rather than array. Any idea?

exec(' bash -ic "expecto \\"sudo bash -ic \\\\\\"rd ; backup_important_batch\\\\\\"\\" $PASSWORD" ', (error, stdout, stderr) => {
    if ( error ){ console.log(error) }
    if ( stdout ){ console.log(stdout) }
    if ( stderr ){ console.log(stderr) }
});
like image 220
k23j4 Avatar asked Aug 09 '19 12:08

k23j4


People also ask

How do you spawn in node JS?

The spawn function launches a command in a new process and we can use it to pass that command any arguments. For example, here's code to spawn a new process that will execute the pwd command. const { spawn } = require('child_process'); const child = spawn('pwd');

What is Child_process spawn?

child_process.exec() : spawns a shell and runs a command within that shell, passing the stdout and stderr to a callback function when complete.

What is Stdio in Nodejs?

The de facto standard input/output manager for Node.js. After a very long time, finally version 2 is here. The cool stdio module you cannot live without has been rewritten and improved a lot, with Typescript support, promise-based usage and much more. Note: Version 2 stops supporting non promise-based usage.


1 Answers

You can't split on spaces because many command line args may include strings like ./foo.js --bar "Hello Baz", splitting on the string will incorrectly give you "Hello Baz" as arguments.

Use a library like https://www.npmjs.com/package/string-argv to convert the string into arguments that you can pass the string to, get an array result and build your spawn() call.

Edit: Here's an example:

const { spawn } = require('child_process');
const { parseArgsStringToArgv } = require('string-argv');

async function run(command) {
    return new Promise( resolve => {
        let args = parseArgsStringToArgv(command);
        let cmd = args.shift();

        console.log(cmd, args);

        let step = spawn(cmd, args);

        step.stdout.pipe(process.stdout);
        step.stderr.pipe(process.stderr);

        step.on('close', (code) => {
           resolve(code);
        });
    });
}

let name = 'Baz';
let exitCode = await run(`echo "Hello ${name}"`);
like image 181
Jay Proulx Avatar answered Oct 02 '22 14:10

Jay Proulx