簡體   English   中英

如何從自定義節點REPL獲取子進程中的輸入

[英]How to get input in child process from custom node REPL

我正在嘗試創建一個節點repl,並希望產生一個子進程,該進程可以接受用戶輸入,然后將控制權返回給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調用后,它進入循環,不斷詢問問題,再也沒有返回repl ...

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

似乎stdin並未在子進程中被捕獲,並且仍在repl中被捕獲。

如何將控制權傳遞給子進程,直到完成,然后再傳遞回父進程?

nb我願意使用任何其他方式來創建子進程。

a.js進行一些更改即可a.js這項工作。 您需要使用process.stdin.pipe(child.stdin); repl進程的stdin輸入通過管道傳遞到子進程的stdin process.stdin.pipe(child.stdin);

為了獲取數據需要從你到管子進程回到child.stdoutprocess.stdin使用child.stdout.pipe(process.stdout);

也許有更好的跟蹤子進程的方法。 但是我添加了一個標記來標記是否生成了一個子代,並在子代進程關閉時將其重置。

最后,當子進程結束時,使用process.stdin.resume();恢復主進程stdin process.stdin.resume(); ,否則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();
  });

}();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM