uci-remote-code/src/ssh.js

98 lines
2.2 KiB
JavaScript

const fs = require('fs')
const EventEmitter = require('events').EventEmitter
const ssh = require('ssh2')
const Client = ssh.Client
class Ssh extends Client {
constructor() {
super()
this._emitter = new EventEmitter()
this._ignoreStdOut = []
return this.init()
}
init() {
const conn = this
conn.on('ready', () => {
conn.shell((err, stream) => {
if (err) {
throw err
}
this.stream = stream
this._emit('connect', 'Connection established')
stream.on('close', () => {
this._emit('close', 'Connection closed')
conn.end()
})
stream.on('data', data => this._emit('data', data))
stream.stderr.on('data', data => this._emit('error', data))
})
})
return this
}
connect(opts = {}) {
opts.privateKey = opts.keyfilePath ? fs.readFileSync(opts.keyfilePath) : null
super.connect(opts)
return new Promise(resolve => {
this.getEventEmitter().on('connect', () => resolve(this))
})
}
getEventEmitter() {
return this._emitter
}
_emit(...args) {
this._emitter.emit(...args)
}
send(line) {
this._ignoreStdOut.push(line)
if (this.stream.writable) {
this.stream.write(`${line}\n`)
}
}
close() {
this.end()
this.stream = null
return this
}
// Supercedes ssh2.exec
// execute a single command on the server and close & resolve
// uses interactive shell to get stdout/stderr back
// stdout, stderr are streams
exec(opts, command = 'uptime', stdout, stderr) {
let data = ''
console.log('executing', opts, command)
return new Promise((resolve, reject) => {
this
.on('ready', () => {
this.shell((err, stream) => {
stream
.on('close', () => {
this.end()
resolve(data)
})
.on('data', s => {
data += s
stdout.write(s)
})
.stderr.on('data', s => {
data += s
stderr.write(s)
})
stream.end(command + '\nexit\n')
})
})
.on('error', e => reject(e))
.connect(opts)
})
}
}
module.exports = Ssh