Nodejs子进程:如何从已初始化的进程中向标准输入写入数据

73

我正在尝试使用Node.js的child_process来启动一个外部进程phantomjs,并在初始化后向该进程发送信息,这是否可能?

以下是我的代码:

var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding = 'utf-8';
child.stdout.pipe(process.stdout);

child.stdin.write("console.log('Hello from PhantomJS')");

但是我在标准输出(stdout)上只得到了PhantomJS控制台的初始提示。

phantomjs> 

因此,看起来 child.stdin.write 没有产生任何影响。

我不确定在初始生成之后是否可以向phantomjs发送附加信息。


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

132

你需要传递\n符号才能使命令生效:

var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);

child.stdin.write("console.log('Hello from PhantomJS')\n");

child.stdin.end(); /// this call seems necessary, at least with plain node.js executable

1
我添加了 child.stdin.end() 调用。 - Alexander Mills
9
由于\r\n是触发write向管道传输新行的行终止符,所以建议使用CLRF。实际上,child.stdout.pipe(process.stdout);是不必要的。 - loretoparisi
8
child.stdin.end() 的调用非常关键。在找到这个方法之前,我苦恼了一段时间。感谢 @AlexanderMills。 - karmakaze
5
@AlexanderMills的child.stdin.end()不是关键的,但在我的情况下,我需要让进程保持开启状态并按照我的要求写入一些文本到tts命令中(这样会更快)。而且没有使用child.stdin.end()也能够正常工作 [\r\n 是关键的部分,这很常见]。我正在生成powershell.exe进程,不知道phantomjs的情况。请问对于你来说有何不同,为什么它对你很重要?谢谢。 - Mohamed Allal
1
添加stdin.end会对我创建一个无限循环。在我的情况下,我希望进程等待下一个用户输入并保持打开状态。 - Alok Rajasukumaran
显示剩余3条评论

5
你需要使用和来包装你的方法,方法会刷新自调用以来缓冲的所有数据。child.stdin.end()也可以刷新数据,但不再接受更多数据。
var spawn = require('child_process').spawn,
    child = spawn('phantomjs');

child.stdin.setEncoding('utf-8');
child.stdout.pipe(process.stdout);

child.stdin.cork();
child.stdin.write("console.log('Hello from PhantomJS')\n");
child.stdin.uncork();

你能帮我解决这个问题吗:https://stackoverflow.com/questions/77501287/macos-nodejs-open-the-terminal-by-passing-the-command-to-execute - undefined

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