如何将标准输入传递给Node.js子进程

20

我正在使用一个node.js中包装pandoc的库。但是我无法弄清楚如何将STDIN传递给子进程`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);
});

在命令行界面上,它看起来像这样:
echo "# Hello World" | pandoc -f markdown -t html

更新 1

尝试使用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?

如果有人正在使用IPC和JSON序列化,我观察到它使用send()函数从子进程发送消息到父进程,但不支持从父进程发送消息到子进程。当我使用fork而不是spawn时,它开始双向发送消息。 - Ankur Thakur
5个回答

20

spawn()类似,execFile()也返回一个ChildProcess实例,该实例拥有一个可写的stdin流。

作为使用write()并监听data事件的替代方法,您可以创建一个可读流,将输入数据push()进去,然后将其pipe()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);

16

以下是我使它工作的方法:

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();

13

将字符串作为标准输入

如果您正在使用同步方法(execFileSyncexecSyncspawnSync),则可以使用选项中的input键将字符串作为标准输入传递。像这样:

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

1

根据这些文档和以下摘录,似乎只能将STDINchild_process.spawn()一起使用,而无法在child_process.execFile()中使用。

child_process.execFile()函数类似于child_process.exec(),但它不会生成一个shell。相反,指定的可执行文件将直接作为新进程生成,使其比child_process.exec()略微更有效率。


@emersonthis,请跟随我在答案中发布的文档链接,其中展示了如何在代码片段中实现。 - peteb
@emersonthis,请在您的问题中更新child_process.spawn()代码,也许另一双眼睛会有所帮助? - peteb
你尝试过在 child_process.spawn() 中添加选项 { stdio: [ 0, 'pipe', 'pipe' ] } 吗? - peteb
是的。我已经用那个更新了问题中的代码。无论我做什么,都会出现“TypeError: Cannot read property 'write' of null”的错误。 - emersonthis
如果我能看到一个将 STDIN 传递给子进程的工作示例,我相信我自己可以解决这个问题...无论是文档链接还是代码片段都可以。任何东西都会有所帮助。 - emersonthis

1

stdin可以通过execexecFileChildProcess实例一起传递。

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();

参考资料:https://github.com/nodejs/node/issues/25231

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接