emersonthis
emersonthis

Reputation: 33378

How to pass STDIN to node.js child process

I'm using a library that wraps pandoc for node. But I can't figure out how to pass STDIN to the child process `execFile...

var execFile = require('child_process').execFile;
var optipng = require('pandoc-bin').path;

// STDIN SHOULD GO HERE!
execFile(optipng, ['--from=markdown', '--to=html'], function (err, stdout, stderr) {
    console.log(err);
    console.log(stdout);
    console.log(stderr);
});

On the CLI it would look like this:

echo "# Hello World" | pandoc -f markdown -t html

UPDATE 1

Trying to get it working with spawn:

var cp = require('child_process');
var optipng = require('pandoc-bin').path;
var child = cp.spawn(optipng, ['--from=markdown', '--to=html'], { stdio: [ 0, 'pipe', 'pipe' ] });

child.stdin.write('# HELLO');
// then what?

Upvotes: 20

Views: 28312

Answers (5)

aGuegu
aGuegu

Reputation: 2299

stdin could be pass into exec and execFile with the ChildProcess instance.

const { exec } = require('node:child_process');

const child = exec('cat', (error, stdout, stderr) => {
    if (error) {
        throw error;
    }
    console.log(stdout);
});

child.stdin.write('foo');
child.stdin.end();

reference: https://github.com/nodejs/node/issues/25231

Upvotes: 1

Marcelo Lazaroni
Marcelo Lazaroni

Reputation: 10239

String as STDIN

If you are using synchronous methods (execFileSync, execSync, or spawnSync) you can pass a string as stdin using the input key in options. Like this:

const child_process = require("child_process");
const str = "some string";
const result = child_process.spawnSync("somecommand", ["arg1", "arg2"], { input: str });

Upvotes: 14

TachyonVortex
TachyonVortex

Reputation: 8572

Like spawn(), execFile() also returns a ChildProcess instance which has a stdin writable stream.

As an alternative to using write() and listening for the data event, you could create a readable stream, push() your input data, and then pipe() it to child.stdin:

var execFile = require('child_process').execFile;
var stream   = require('stream');
var optipng  = require('pandoc-bin').path;

var child = execFile(optipng, ['--from=markdown', '--to=html'], function (err, stdout, stderr) {
    console.log(err);
    console.log(stdout);
    console.log(stderr);
});

var input = '# HELLO';

var stdinStream = new stream.Readable();
stdinStream.push(input);  // Add data to the internal queue for users of the stream to consume
stdinStream.push(null);   // Signals the end of the stream (EOF)
stdinStream.pipe(child.stdin);

Upvotes: 21

emersonthis
emersonthis

Reputation: 33378

Here's how I got it to work:

var cp = require('child_process');
var optipng = require('pandoc-bin').path; //This is a path to a command
var child = cp.spawn(optipng, ['--from=markdown', '--to=html']); //the array is the arguments

child.stdin.write('# HELLO'); //my command takes a markdown string...

child.stdout.on('data', function (data) {
    console.log('stdout: ' + data);
});
child.stdin.end();

Upvotes: 17

peteb
peteb

Reputation: 19428

I'm not sure its possible to use STDIN with child_process.execFile() based on these docs and the below excerpt, looks like its available only to child_process.spawn()

The child_process.execFile() function is similar to child_process.exec() except that it does not spawn a shell. Rather, the specified executable file is spawned directly as a new process making it slightly more efficient than child_process.exec().

Upvotes: 1

Related Questions