javascript 如何在 node.js 中运行交互式 shell 命令?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27458502/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to run interactive shell command inside node.js?
提问by Wunsch Punsch
I have to run some interactive shell command inside node.js. Lets our interactive shell be $ python
:
我必须在 node.js 中运行一些交互式 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();
This code does not output anything (but stdout should be 2
).
此代码不输出任何内容(但 stdout 应该是2
)。
But if it would, there will be another problem: how to make it interactive? The process ends when I call pythonChildProcess.stdin.end();
! But I just wanted to end stdin and write next stdin!
但如果是这样,就会出现另一个问题:如何使其具有交互性?当我打电话时,过程结束pythonChildProcess.stdin.end();
!但我只想结束标准输入并编写下一个标准输入!
UPD:
If I could emulate pressing of enter
button - I would be able to interactively write to the process. But adding \n
to the end of the input string does not help.
UPD:如果我可以模拟按下enter
按钮 - 我将能够以交互方式写入该过程。但是添加\n
到输入字符串的末尾无济于事。
采纳答案by E_net4 the Rustacean
First and foremost, one of the things preventing node from interfacing with other interactive shells is that the child application must keep its "interactive" behavior, even when stdin
doesn't look like a terminal. python
here knew that its stdin
wasn't a terminal, so it refused to work. This can be overridden by adding the -i
flag to the python command.
首先也是最重要的,阻止节点与其他交互式 shell 交互的一件事是子应用程序必须保持其“交互式”行为,即使stdin
看起来不像终端。python
这里知道它stdin
不是终端,所以它拒绝工作。这可以通过将-i
标志添加到 python 命令来覆盖。
Second, as you well mentioned in the update, you forgot to write a new line character to the stream, so the program behaved as if the user didn't press Enter. Yes, this is the right way to go, but the lack of an interactive mode prevented you from retrieving any results.
其次,正如您在更新中提到的那样,您忘记向流中写入换行符,因此程序的行为就像用户没有按 Enter 键一样。是的,这是正确的方法,但是缺少交互模式使您无法检索任何结果。
Here's something you can do to send multiple inputs to the interactive shell, while still being able to retrieve each result one by one. This code will be resistant to lengthy outputs, accumulating them until a full line is received before performing another instruction. Multiple instructions can be performed at a time as well, which may be preferable if they don't depend on the parent process' state. Feel free to experiment with other asynchronous structures to fulfil your goal.
您可以执行以下操作将多个输入发送到交互式 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');
回答by Adam
This works great for me:
这对我很有用:
const { spawn } = require('child_process')
const shell = spawn('sh',[], { stdio: 'inherit' })
shell.on('close',(code)=>{console.log('[shell] terminated :',code)})
回答by Jayant Bhawal
A tl;dr version of @E_net4's answer, for those who understand just by reading the code. For a detailed explanation, please do read his answer. He has described it well.
@E_net4 答案的 tl;dr 版本,适用于仅通过阅读代码即可理解的人。有关详细说明,请阅读他的回答。他描述得很好。
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');
Output:
输出:
>
1