如何从自定义节点REPL获取subprocess的input

我正在尝试创build一个节点repl,并希望产生一个subprocess,它可以接受用户input,然后将控制返回给repl。

主repl文件的内容( a.js

 !function(){ var repl = require("repl"), spawn = require('child_process').spawn; function eval(cmd, context, filename, callback) { var child = spawn('node', ['./b.js']); child.stdout.pipe(process.stdout); child.stdin.pipe(process.stdin); child.on('close', function (code) { console.log('closing') callback(code, 'closing callback'); }); } repl.start({ prompt: 'repl> ', input: process.stdin, output: process.stdout, eval: eval }).on('exit', function () { process.exit(); }); }(); 

…在subprocess中调用的脚本的内容( b.js

 !function(){ promptly = require('promptly'); promptly.prompt('some question: ', function (err, answer) { console.log(answer); process.exit(); }); }(); 

当我运行node b所有是如预期的…

 $ node b some question: something something $ 

但是,从repl调用,它进入循环,它一直在问问题,永远不会返回到repl …

 $ node a repl> anything some question: my answer some question: another answer some question: etc... 

看来stdin并没有在subprocess中被捕获,而且它仍然被repl捕获。

我如何将控制权交给subprocess,直到完成,然后传递给父进程?

我打开使用任何其他手段来创buildsubprocess。

a.js的一些改变应该使这个工作。 您需要使用process.stdin.pipe(child.stdin);pipe道从主repl进程的stdin到subprocess的stdin process.stdin.pipe(child.stdin);

为了从subprocess获取数据,需要使用child.stdout.pipe(process.stdout);child.stdout传递给process.stdin child.stdout.pipe(process.stdout);

也许有更好的方法来跟踪subprocess。 但是我添加了一个标记来标记是否产生了一个孩子,并在孩subprocessclosures时重置它。

最后,当subprocess结束时,用process.stdin.resume();恢复主进程stdin process.stdin.resume(); ,否则repl将停止在下一个input。

 !function(){ var repl = require("repl"), spawn = require('child_process').spawn; var child_spawned = false; function eval(cmd, context, filename, callback) { // don't start a new child process if one is already running if(child_spawned) return; var child = spawn('node', ['./b.js']); child_spawned = true; // pipe child output back up to parent process child.stdout.pipe(process.stdout); // pipe the main process input to the child process process.stdin.pipe(child.stdin); child.on('close', function (code) { console.log('closing') callback(code, 'closing callback'); // mark child process as closed child_spawned = false; // resume the main process stdin after child ends so the repl continues to run process.stdin.resume(); }); } repl.start({ prompt: 'repl> ', input: process.stdin, output: process.stdout, eval: eval }).on('exit', function () { process.exit(); }); }(); 

我通过使用spawnSync (简化stream)和{ stdio: 'inherit' }作为传递选项的组合来解决此问题。

 !function(){ var repl = require("repl"), spawnSync = require('child_process').spawnSync; function eval(cmd, context, filename, callback) { spawnSync('node', ['./b.js'], { stdio: 'inherit' }); callback(); } repl.start({ prompt: 'repl> ', input: process.stdin, output: process.stdout, eval: eval }).on('exit', function () { process.exit(); }); }();