如何从自定义节点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(); }); }();