如何从自定义节点 REPL 获取子进程的输入
How to get input in child process from custom node REPL
我正在尝试创建一个节点 repl,并想生成一个子进程,它可以接收用户输入,然后 return 控制权返回 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();
});
}();
...子进程中调用的脚本内容 (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 调用,它进入循环,它一直在问问题,从不 returns 到 repl...
$ node a
repl> anything
some question: my answer
some question: another answer
some question: etc...
好像stdin在子进程中没有被捕获,repl中还在捕获。
如何将控制传递给子进程,直到它完成,然后再传递回父进程?
n.b。我愿意使用任何其他方式创建子进程。
对 a.js
的一些更改应该可以完成这项工作。您需要使用 process.stdin.pipe(child.stdin);
将来自主 repl 进程的 stdin
输入通过管道传输到子进程的 stdin
要从子进程取回数据,您需要使用 child.stdout.pipe(process.stdout);
将 child.stdout
传输到 process.stdin
也许有更好的方法来跟踪子进程。但是我添加了一个标志来标记是否生成了一个子进程,并在子进程关闭时重置它。
最后,当子进程结束时,用process.stdin.resume();
恢复主进程stdin
,否则repl将在下一个输入时停止。
!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
(以简化流程)和 { 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();
});
}();
我正在尝试创建一个节点 repl,并想生成一个子进程,它可以接收用户输入,然后 return 控制权返回 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();
});
}();
...子进程中调用的脚本内容 (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 调用,它进入循环,它一直在问问题,从不 returns 到 repl...
$ node a
repl> anything
some question: my answer
some question: another answer
some question: etc...
好像stdin在子进程中没有被捕获,repl中还在捕获。
如何将控制传递给子进程,直到它完成,然后再传递回父进程?
n.b。我愿意使用任何其他方式创建子进程。
对 a.js
的一些更改应该可以完成这项工作。您需要使用 process.stdin.pipe(child.stdin);
stdin
输入通过管道传输到子进程的 stdin
要从子进程取回数据,您需要使用 child.stdout.pipe(process.stdout);
child.stdout
传输到 process.stdin
也许有更好的方法来跟踪子进程。但是我添加了一个标志来标记是否生成了一个子进程,并在子进程关闭时重置它。
最后,当子进程结束时,用process.stdin.resume();
恢复主进程stdin
,否则repl将在下一个输入时停止。
!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
(以简化流程)和 { 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();
});
}();