Javascript 如何在node.js中运行交互式shell命令?

Javascript 如何在node.js中运行交互式shell命令?,javascript,node.js,shell,Javascript,Node.js,Shell,我必须在node.js中运行一些交互式shell命令。让我们的交互式shell成为$python: var cp = require('child_process'); var pythonChildProcess = cp.spawn('python'); pythonChildProcess.stdout.on("data", function(data) { console.log('data successfully written!', data); // never outpu

我必须在node.js中运行一些交互式shell命令。让我们的交互式shell成为
$python

var cp = require('child_process');
var pythonChildProcess = cp.spawn('python');

pythonChildProcess.stdout.on("data", function(data) {
  console.log('data successfully written!', data); // never outputs anything
});

pythonChildProcess.stdin.write('1 + 1');
pythonChildProcess.stdin.end();
此代码不输出任何内容(但标准输出应该是
2


但如果它真的这样做了,那么还有另一个问题:如何让它具有互动性?当我调用
pythonChildProcess.stdin.end()时,进程结束!但我只是想结束stdin,然后写下一个stdin

UPD:
如果我可以模拟按下
enter
按钮,我将能够以交互方式写入进程。但是将
\n
添加到输入字符串的末尾并没有帮助。

首先,阻止节点与其他交互式shell交互的一个因素是,子应用程序必须保持其“交互式”行为,即使
stdin
看起来不像终端
python
这里知道它的
stdin
不是终端,所以它拒绝工作。这可以通过向python命令添加
-i
标志来覆盖

其次,正如您在更新中提到的,您忘记了向流中写入新行字符,因此程序的行为就像用户没有按Enter键一样。 是的,这是正确的方法,但是由于缺乏交互模式,您无法检索任何结果

您可以这样做,将多个输入发送到交互式shell,同时仍然能够逐个检索每个结果。此代码将抵抗冗长的输出,在执行另一条指令之前,将它们累积到接收到一整行。也可以一次执行多条指令,如果它们不依赖于父进程的状态,这可能更可取。请随意尝试其他异步结构以实现您的目标

var cp = require('child_process');
var childProcess = cp.spawn('python', ['-i']);

childProcess.stdout.setEncoding('utf8')

var k = 0;
var data_line = '';

childProcess.stdout.on("data", function(data) {
  data_line += data;
  if (data_line[data_line.length-1] == '\n') {
    // we've got new data (assuming each individual output ends with '\n')
    var res = parseFloat(data_line);
    data_line = ''; // reset the line of data

    console.log('Result #', k, ': ', res);

    k++;
    // do something else now
    if (k < 5) {
      // double the previous result
      childProcess.stdin.write('2 * + ' + res + '\n');
    } else {
      // that's enough
      childProcess.stdin.end();
    }
  }
});


childProcess.stdin.write('1 + 0\n');
var cp=require('child_process');
var childProcess=cp.spawn('python',['-i']);
childProcess.stdout.setEncoding('utf8')
var k=0;
var数据线=“”;
childProcess.stdout.on(“数据”,函数(数据){
数据线+=数据;
如果(数据线[数据线.长度-1]='\n'){
//我们获得了新数据(假设每个单独的输出以“\n”结尾)
var res=解析浮点(数据线);
data_line='';//重置数据行
log('Result#',k',:',res);
k++;
//现在做点别的吧
if(k<5){
//比先前的结果加倍
childProcess.stdin.write('2*+'+res+'\n');
}否则{
//够了
childProcess.stdin.end();
}
}
});
childProcess.stdin.write('1+0\n');

A tl;dr版本的@E_net4答案,供那些只需阅读代码就能理解的人使用。欲知详细解释,请务必阅读他的答案。他描述得很好

var spawn = require('child_process').spawn

var p = spawn('node',['-i']);

p.stdout.on('data',function (data) {
    console.log(data.toString())
});

p.stdin.write('1 + 0\n');
输出:

> 
1

这对我来说非常有用:

const { spawn } = require('child_process')
const shell = spawn('sh',[], { stdio: 'inherit' })
shell.on('close',(code)=>{console.log('[shell] terminated :',code)})

“结束stdin并写入下一个stdin”?你能解释一下你的意思吗?@E_net4,我想执行
$python
命令,写一些输入(例如
1+1
),“按
enter
”,得到一些输出(
2
),然后写另一个输入(
10+10
),“再按
enter
”,得到另一个输出,然后写一些其他的输入,等等。。。这些我称之为“stdins”的“输入”序列实际上是一个单一的stdin流,你想向其中发送多行输入。这正是我想要的!完美的解决方案。不确定我错过了什么;交互部分在哪里?那将是
stdio:'inherit'
。您可以在这里阅读不同的选项:但有一些警告:这只适用于python,如何使其适用于任何任意程序?@Rainb除了程序名之外,还假设当需要用户输入时,程序的输出以新行结束。如果不是这样,则需要相应地调整程序。我不认为这里有银弹。把你的问题变成一个新问题。