Use child_process#spawn with a generic string

591 views Asked by At

I have a script in the form of a string that I would like to execute in a Node.js child process.

The data looks like this:

const script = {
    str: 'cd bar && fee fi fo fum',
    interpreter: 'zsh'
};

Normally, I could use

const exec = [script.str,'|',script.interpreter].join(' ');

const cp = require('child_process');
cp.exec(exec, function(err,stdout,sterr){});

however, cp.exec buffers the stdout/stderr, and I would like to be able to be able to stream stdout/stderr to wherever.

does anyone know if there is a way to use cp.spawn in some way with a generic string, in the same way you can use cp.exec? I would like to avoid writing the string to a temporary file and then executing the file with cp.spawn.

cp.spawn will work with a string but only if it has a predictable format - this is for a library so it needs to be extremely generic.

...I just thought of something, I am guessing the best way to do this is:

const n = cp.spawn(script.interpreter);
n.stdin.write(script.str);   // <<< key part

n.stdout.setEncoding('utf8');

n.stdout.pipe(fs.createWriteStream('./wherever'));

I will try that out, but maybe someone has a better idea.

downvoter: you are useless

1

There are 1 answers

0
Alexander Mills On BEST ANSWER

Ok figured this out.

I used the answer from this question: Nodejs Child Process: write to stdin from an already initialised process

The following allows you to feed a generic string to a child process, with different shell interpreters, the following uses zsh, but you could use bash or sh or whatever executable really.

const cp = require('child_process');

const n = cp.spawn('zsh');

n.stdin.setEncoding('utf8');
n.stdin.write('echo "bar"\n');   // <<< key part, you must use newline char

n.stdout.setEncoding('utf8');

n.stdout.on('data', function(d){
    console.log('data => ', d);
});

Using Node.js, it's about the same, but seems like I need to use one extra call, that is, n.stdin.end(), like so:

const cp = require('child_process');

const n = cp.spawn('node').on('error', function(e){
    console.error(e.stack || e);
});

n.stdin.setEncoding('utf-8');
n.stdin.write("\n console.log(require('util').inspect({zim:'zam'}));\n\n");   // <<< key part

n.stdin.end();   /// seems necessary to call .end()

n.stdout.setEncoding('utf8');

n.stdout.on('data', function(d){
    console.log('data => ', d);
});