【发布时间】:2018-06-20 07:31:04
【问题描述】:
我正在构建一个 node.js 应用程序,该应用程序在生产中将充当许多服务器的 SSH 客户端,其中一些服务器可能在任何给定时间都无法访问。我正在尝试编写一个函数,该函数尝试在启动时对其配置中的每个客户端运行 SSH 命令,但我无法同时处理成功的会话和以错误结束的会话。我在一个承诺中包装了一个 ssh2 客户端。如果我删除了第三个(垃圾)服务器并且只有成功的结果,这很好!查看输出:
STDOUT: Hello World
STDOUT: Hello World
Session closed
Session closed
Successful session: Hello World,Hello World
但是,如果其中一个连接超时,即使我处理了错误,我也无法保留我的任何数据。看起来错误消息覆盖了所有已解决的承诺
Successful session: Error: Timed out while waiting for handshake,Error:
Timed out while waiting for handshake,Error: Timed out while waiting
for handshake
这是我的代码,如果这有点分散,请原谅我,因为为了这个问题,我已经组合了一些模块。我的目标是保留成功会话中的数据并优雅地处理失败。
var Client = require('ssh2').Client;
const labs = {
"ny1": "192.168.1.2",
"ny2": "192.168.1.3",
"ny3": "1.1.1.1"
};
function checkLabs() {
let numLabs = Object.keys(labs).length;
let promises = [];
for(i=0;i<numLabs;i++){
let labName = Object.keys(labs)[i];
promises.push(asyncSSH("echo 'Hello World'", labs[labName]));
}
Promise.all(promises.map(p => p.catch(e => e)))
.then(results => console.log("Successful session: " + results))
.catch(e => console.log("Error! " + e));
}
var sendSSH = function (command, dest, callback) {
var conn = new Client();
conn.on('ready', function() {
return conn.exec(command, function(err, stream) {
if (err) throw err;
stream.on('data', function(data) {
callback(null, data);
console.log('STDOUT: ' + data);
}).stderr.on('data', function(data){
callback(err);
console.log('STDERR: ' + data);
}).on('close', function(err) {
if(err) {
console.log('Session closed due to error');
} else {
console.log('Session closed');
}
});
stream.end('ls -l\nexit\n');
});
}).on('error', function(err){
callback(err);
}).connect({
host: dest,
port: 22,
username: 'root',
readyTimeout: 10000,
privateKey: require('fs').readFileSync('link-to-my-key')
});
};
function asyncSSH(command, dest) {
return new Promise(function(resolve, reject){
sendSSH(command, dest, function(err,data) {
if (!err) {
resolve(data);
} else {
reject(err);
}
});
});
}
checklabs();
如何更好地使用这个 promise 包装器来处理来自 ssh2 客户端的任何错误?任何提示都表示赞赏。
【问题讨论】:
-
变量 conn 似乎不知从何而来,神奇地存在。不知道为什么你定义
labs而不是const labs = {... -
您只能解决或拒绝一次承诺,但您可以解决多次,因为数据发生了多次。这不会导致错误,但在第一个之后的任何调用 resolve 都将被忽略。相反,您应该在关闭时解析并将数据保存在数组中的任何数据,以便您可以在关闭时使用该数组解析。不过,这看起来不像您可以实际运行并演示您的问题的任何代码。
-
@HMR 这很有帮助,谢谢。我在一个单独的文件中使用了define方法来充当配置,也许我应该称它为const。如果我删除了 ssh2 代码并在伪代码中展示了成功/错误,那么实现这一点作为演示会更有用。我想处理 ssh2 行为对我的问题非常重要,我需要花更多时间处理这部分。
-
为了让问题更上一层楼,我的问题是我需要使用同一段 ssh2 代码进行多个事务。每个都关闭,在这种情况下
.on('data'API 会成功关闭,在连接失败的情况下会导致close或.on('error'。每个事务可能需要长达 10 秒的超时时间。我不在乎它们是同步发生还是异步发生,我只需要保存每个数据,并优雅地处理发生的任何错误,恢复任何剩余的 ssh 会话。 -
似乎有点奇怪,您应该使用
Client()的单个实例来达到“Hello World,Hello World”。我原以为您需要(a)每个主机一个实例,或(b)执行串联连接。如果回显的消息包含独特的内容,例如ny1/ny2键,会发生什么情况。
标签: javascript node.js ssh promise