为什么在使用shell时,javascript ssh2会陷入无限循环

我试图让我的应用程序通过使用ssh2 npm包在另一个系统上执行sudo命令。 我有最终的结果工作,但由于某种原因,代码陷入了一个无限循环。 我不明白这是如何可能的,因为我认为用conn.endclosures连接会防止这种情况发生。 任何人都可以帮助解释为什么我在这里陷入无限循环?

正在执行的主要代码:

function sshRunSudoCommand(user, pass, lanIP, command) { return new Promise((resolve, reject) => { var Connection = require('ssh2'); var pwSent = false; var sudosu = false; var password = pass; var conn = new Connection(); conn.on('ready', function() { console.log('Sudo Connection :: ready'); conn.shell( function(err, stream) { if (err) throw err; stream .on('close', function() { console.log('Sudo Stream :: close'); conn.end(); resolve(); }) .on('data', function(data) { //handle sudo password prompt stream.write(password + '\n'); stream.write(command + '\n'); console.log('Sudo STDOUT: ' + data); resolve(data); }) .on('exit', function(code, signal) { let exitCode = 'Stream :: exit :: code: ' + code + ', signal: ' + signal; conn.end(); resolve(exitCode); }) .on('end', function() { conn.end(); resolve('end'); }) .stderr.on('data', function(data) { console.log('STDERR: ' + data); conn.end(); resolve(data); }); }); }) .on('keyboard-interactive', function(name, instructions, instructionsLang, prompts, finish) { // Pass answers to `prompts` to `finish()`. Typically `prompts.length === 1` // with `prompts[0] === "Password: "` console.log('pass before finish is ', pass); finish([pass]); }).on('ready', function() { }).connect({ host: lanIP, port: 22, username: user, password: pass, readyTimeout: 99999, tryKeyboard: true // this attempts keyboard-interactive auth }); }; } 

结果:(永远重复)

 Sudo STDOUT: activedash:~ activeadmin$ s Sudo STDOUT: udo Sudo STDOUT: profiles -I - Sudo STDOUT: F /Users/S Sudo STDOUT: hared/Sym Sudo STDOUT: ply/activ Sudo STDOUT: e-uuid. onfigpr Sudo STDOUT: ofile Sudo STDOUT: active sudo profiles -I -F /Users/Shared/Symply/active-uuid.configprofile active sudo profiles -I -F /Users/Shared/Symply/active-uuid.configprofile active sudo profiles -I -F /Users/Shared/Symply/active-uuid.configprofile active sudo profiles -I -F /Users/Shared/Symply/active-uuid.configprofile active sudo profiles 

所以我发现有两件事我需要做,以防止重复行动。

  1. 我需要添加'exit'命令到stream.write来告诉shell结束我用conn.shell创build的会话

  2. 然后,我可以将我的resolve()callback移到代码的.on('exit)部分,只有在我成功运行exit命令后才能回来。

最终的代码如下所示:

 function sshRunSudoCommand(user, pass, lanIP, command) { return new Promise((resolve, reject) => { var Connection = require('ssh2'); var password = pass; var conn = new Connection(); conn.on('ready', function() { console.log('Sudo Connection :: ready'); conn.shell( function(err, stream) { if (err) throw err; stream .on('close', function() { console.log('Sudo Stream :: close'); conn.end(); resolve(); }) .on('data', function(data) { //handle sudo password prompt stream.write(password + '\n'); stream.write(command + '\n'); stream.write('exit\n'); }) .on('exit', function(code, signal) { let exitCode = 'Stream :: exit :: code: ' + code + ', signal: ' + signal; conn.end(); resolve(exitCode); }) .on('end', function() { conn.end(); resolve('end'); }) .stderr.on('data', function(data) { console.log('STDERR: ' + data); conn.end(); resolve(data); }); }); }) .on('keyboard-interactive', function(name, instructions, instructionsLang, prompts, finish) { // Pass answers to `prompts` to `finish()`. Typically `prompts.length === 1` // with `prompts[0] === "Password: "` console.log('pass before finish is ', pass); finish([pass]); }).on('ready', function() { }).connect({ host: lanIP, port: 22, username: user, password: pass, readyTimeout: 99999, tryKeyboard: true // this attempts keyboard-interactive auth }); }; }