I'm working on simple CLI, one of it's function is to run ssh to remote servers. This is an example of what I mean:
我正在处理简单的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();
I use iface.pause() to make child process able to read from STDIN exclusively, if I remove this line, some symbols will be catched by remote server, another ones - by local readline. But this pause()
really freezes stdin so if ssh waits for connect too long or trying to ask me for password, I can't send any character because stdin is paused. I don't really know how ssh handles (paused?) stdin after successful connect but somehow it works. The question is "How to detach stdin from readline without pausing it while interactive child process is working and to attach it back after child process is finished?"
我使用iface.pause()使子进程能够完全从STDIN中读取,如果我删除这一行,一些符号将被远程服务器捕获,另一些符号将被本地读线捕获。但是这个pause()实际上冻结了stdin,所以如果ssh等待连接太长或试图向我询问密码,我就不能发送任何字符,因为stdin已经暂停。我不太清楚ssh在成功连接后是如何处理(暂停?)stdin的,但不知何故它可以工作。问题是“如何从readline中分离stdin而不暂停,而交互的子进程正在工作,并且在子进程完成后将其附加到后面?”
2 个解决方案
#1
4
The problem was solved by adding setRawMode(false)
right before spawning process. As far as I understand, this makes node release stdin from any transformations it makes to handle keypresses of functional keys. Solved version of code follows:
这个问题是通过在产卵之前添加setRawMode(false)来解决的。据我所知,这使得node将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();
});
});
#2
0
For what it's worth, one solution to this problem may be to just not use child processes for doing ssh client connections. There is a pure-JavaScript ssh client for node called ssh2
. Not only would it be more lightweight than spawning a bunch of child processes, but it may be a lot easier to work with.
值得注意的是,这个问题的一个解决方案可能是不使用子进程来进行ssh客户机连接。有一个名为ssh2的纯javascript ssh客户端。它不仅比生成一堆子进程更轻,而且可能更容易处理。
#1
4
The problem was solved by adding setRawMode(false)
right before spawning process. As far as I understand, this makes node release stdin from any transformations it makes to handle keypresses of functional keys. Solved version of code follows:
这个问题是通过在产卵之前添加setRawMode(false)来解决的。据我所知,这使得node将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();
});
});
#2
0
For what it's worth, one solution to this problem may be to just not use child processes for doing ssh client connections. There is a pure-JavaScript ssh client for node called ssh2
. Not only would it be more lightweight than spawning a bunch of child processes, but it may be a lot easier to work with.
值得注意的是,这个问题的一个解决方案可能是不使用子进程来进行ssh客户机连接。有一个名为ssh2的纯javascript ssh客户端。它不仅比生成一堆子进程更轻,而且可能更容易处理。