我正在使用简单的CLI,其中一个功能是将ssh运行到远程服务器。 这是我的意思的一个例子:
#!/usr/bin/env node
var spawn = require('child_process').spawn;
var readline = require('readline');
var iface =readline.createInterface({
input: process.stdin,
output: process.stdout
});
iface.setPrompt("host> ");
iface.on("line", function(line) {
if (line.trim() == "") {
return iface.prompt();
}
var host = line.split()[0];
iface.pause(); // PAUSING STDIN!
var proc = spawn('ssh', [ host, '-l', 'root', '-o', 'ConnectTimeout=4' ], { stdio: [0,1,2] });
proc.on("exit", function(code, signal) {
iface.prompt();
});
});
iface.prompt();
我使用iface.pause()使子进程能够独占于STDIN读取,如果我删除此行,一些符号将由远程服务器捕获,另一个符号将由本地readline捕获。
但是这个pause()
确实冻结了stdin,所以如果ssh等待连接太长或者试图要求我输入密码,我就无法发送任何字符,因为stdin已经暂停了。在成功连接之后,我真的不知道ssh如何处理(暂停?)stdin,但不知何故它有效。问题是"如何在交互式子进程工作时将stdin与readline分离而不将其暂停并在子进程完成后将其附加回来?"
答案 0 :(得分:4)
通过在产卵过程之前添加setRawMode(false)
来解决问题。据我所知,这使得节点释放stdin来处理它为处理功能键的按键所做的任何转换。解决的代码版本如下:
var spawn = require('child_process').spawn;
var readline = require('readline');
var iface =readline.createInterface({
input: process.stdin,
output: process.stdout
});
iface.setPrompt("host> ");
iface.on("line", function(line) {
if (line.trim() == "") {
return iface.prompt();
}
var host = line.split()[0];
iface.pause(); // PAUSING STDIN!
process.stdin.setRawMode(false); // Releasing stdin
var proc = spawn('ssh', [ host, '-l', 'root', '-o', 'ConnectTimeout=4' ], { stdio: [0,1,2] });
proc.on("exit", function(code, signal) {
// Don't forget to switch pseudo terminal on again
process.stdin.setRawMode(true);
iface.prompt();
});
});
答案 1 :(得分:0)
对于它的价值,这个问题的一个解决方案可能是不使用子进程来执行ssh客户端连接。有一个名为ssh2
的节点的纯JavaScript ssh客户端。它不仅比产生一堆子进程更轻量级,而且可能更容易使用。