我试图让我的应用程序通过使用ssh2 npm包在另一个系统上执行sudo命令。我有最终结果,但由于某种原因,代码陷入了无限循环。我不明白这是怎么可能的,因为我认为用conn.end关闭连接会阻止这种情况发生。任何人都可以帮助解释为什么我会陷入无限循环吗?
正在执行的主要代码:
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
答案 0 :(得分:0)
所以我发现我需要做两件事来防止重复动作。
我需要向stream.write添加和'exit'命令告诉shell结束我用conn.shell创建的会话
然后我可以将我的resolve()回调移动到代码的.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
});
};
}