pull/350/head
midoks 2 years ago
parent 7314071634
commit bf064d89f4
  1. 125
      class/core/ssh_terminal.py
  2. 36
      plugins/webssh/js/webssh.js
  3. 22
      plugins/webssh/menu/index.css
  4. 7
      plugins/webssh/menu/index.html
  5. 77
      route/static/js/term-websocketio.js

@ -53,12 +53,11 @@ class ssh_terminal:
__ps = None
__ssh_list = {}
__ssh_last_request_time = {}
def __init__(self):
# ht = threading.Thread(target=self.heartbeat)
# ht.start()
# ht.join()
pass
ht = threading.Thread(target=self.heartbeat)
ht.start()
def debug(self, msg):
msg = "{} - {}:{} => {} \n".format(mw.formatDate(),
@ -208,6 +207,7 @@ class ssh_terminal:
term='xterm', width=83, height=21)
ssh.setblocking(0)
self.__ssh_list[self.__sid] = ssh
self.__ssh_last_request_time[self.__sid] = time.time()
mw.writeLog(self.__log_type, '成功登录到SSH服务器 [{}:{}]'.format(
self.__host, self.__port))
self.debug('local-ssh:通道已构建')
@ -329,6 +329,7 @@ class ssh_terminal:
ssh.get_pty(term='xterm', width=100, height=34)
ssh.invoke_shell()
self.__ssh_list[self.__sid] = ssh
self.__ssh_last_request_time[self.__sid] = time.time()
mw.writeLog(self.__log_type, '成功登录到SSH服务器 [{}:{}]'.format(
self.__host, self.__port))
self.debug('通道已构建')
@ -355,10 +356,10 @@ class ssh_terminal:
if 'pkey_passwd' in info:
self.__key_passwd = info['pkey_passwd']
print(self.__host, self.__pass, self.__key_passwd)
# print(self.__host, self.__pass, self.__key_passwd)
try:
result = self.connect()
print(result)
# print(result)
except Exception as ex:
if str(ex).find("NoneType") == -1:
raise ex
@ -378,16 +379,13 @@ class ssh_terminal:
except:
pass
def heartbeat(self):
while True:
time.sleep(3)
print("heartbeat:__ssh_list:", len(self.__ssh_list))
# self.debug("heartbeat:__ssh_list:" + str(len(self.__ssh_list)))
# if self.__tp and self.__tp.is_active():
# self.__tp.send_ignore()
# if self.__ps and self.__ps.is_active():
# self.__ps.send_ignore()
def resize(self, data):
try:
self.__ssh_list[self.__sid].resize_pty(
width=data['cols'], height=data['rows'])
return True
except:
return False
def wsSend(self, recv):
try:
@ -396,42 +394,6 @@ class ssh_terminal:
except Exception as e:
return emit('server_response', {'data': recv})
def run(self, sid, info):
# sid = mw.md5(sid)
self.__sid = sid
if not self.__sid:
return self.wsSend('WebSocketIO无效')
if self.__connecting and not 'host' in info:
return
result = self.returnMsg(False, '')
if not sid in self.__ssh_list:
if type(info) == dict:
self.__connecting = True
result = self.setAttr(info)
self.__connecting = False
if sid in self.__ssh_list:
result = self.returnMsg(True, '已连接')
if result['status']:
if type(info) == str:
time.sleep(0.1)
if self.__ssh_list[sid].exit_status_ready():
self.wsSend("logout\r\n")
del(self.__ssh_list[sid])
return
self.__ssh_list[sid].send(info)
try:
time.sleep(0.005)
recv = self.__ssh_list[sid].recv(8192)
return self.wsSend(recv)
except Exception as ex:
return self.wsSend('')
else:
return self.wsSend(result['msg'])
def getSshDir(self):
if mw.isAppleSystem():
user = mw.execShell(
@ -470,3 +432,62 @@ class ssh_terminal:
mw.execShell(cmd)
cmd = 'chmod 600 ' + ssh_dir + '/authorized_keys'
mw.execShell(cmd)
def heartbeat(self):
while True:
time.sleep(3)
cur_time = time.time()
print("heartbeat:cur_time:", cur_time)
print("heartbeat:__ssh_list:", len(self.__ssh_list))
for x in self.__ssh_list:
ssh_last_time = self.__ssh_last_request_time[x]
print(x, self.__ssh_list[x])
# self.debug("heartbeat:__ssh_list:" + str(len(self.__ssh_list)))
# if self.__tp and self.__tp.is_active():
# self.__tp.send_ignore()
# if self.__ps and self.__ps.is_active():
# self.__ps.send_ignore()
def run(self, sid, info):
# sid = mw.md5(sid)
self.__sid = sid
if not self.__sid:
return self.wsSend('WebSocketIO无效')
if self.__connecting and not 'host' in info:
return
result = self.returnMsg(False, '')
if not sid in self.__ssh_list:
if type(info) == dict and 'host' in info:
self.__connecting = True
result = self.setAttr(info)
self.__connecting = False
if sid in self.__ssh_list:
if 'resize' in info:
self.resize(info)
result = self.returnMsg(True, '已连接')
print("req.__ssh_list:", str(len(self.__ssh_list)))
print("req.:cmd:", sid, info)
if result['status']:
if type(info) == str:
time.sleep(0.1)
cur_ssh = self.__ssh_list[sid]
if cur_ssh.exit_status_ready():
self.wsSend("logout\r\n")
del(self.__ssh_list[sid])
return
cur_ssh.send(info)
try:
time.sleep(0.005)
recv = cur_ssh.recv(8192)
return self.wsSend(recv)
except Exception as ex:
return self.wsSend('')
else:
return self.wsSend(result['msg'])

@ -2,6 +2,14 @@
//全局
var host_ssh_list = [];
//刷新页面
$(window).unload(function(){
for (i in host_ssh_list) {
host_ssh_list[i].close();
}
return false;
});
function appPost(method,args,callback){
var _args = null;
if (typeof(args) == 'string'){
@ -68,10 +76,20 @@ $(document).ready(function(){
}
});
function webShell_Resize(){
var cur_ssh = $('.term_item_tab .list .active');
var data = $(cur_ssh).data();
var item = host_ssh_list[data.id];
item.term.focus();
item.term.fit();
item.resize({ cols: item.term.cols, rows: item.term.rows});
}
function webShell_Load(){
changeDivH();
$(window).resize(function(){
changeDivH();
webShell_Resize();
});
$('.term_content_tab .term-tool-button').click(function(){
@ -86,8 +104,11 @@ function webShell_Load(){
$(this).removeClass('tool-hide').addClass('tool-show');
$(this).find('span').removeClass('glyphicon-menu-right').addClass('glyphicon-menu-left');
}
webShell_Resize();
});
$('.full_exit_screen').click(function(ele){
if($(this).hasClass('glyphicon-resize-full')){
requestFullScreen($('#term_box_view')[0]);
@ -112,16 +133,14 @@ function webShell_Load(){
// 切换服务器终端视图
$('.term_item_tab .list').on('click', 'span.item', function (ev) {
var index = $(this).index(), data = $(this).data();
var index = $(this).index();
var data = $(this).data();
if ($(this).hasClass('addServer')) {
} else if ($(this).hasClass('tab_tootls')) {
} else {
$(this).addClass('active').siblings().removeClass('active');
$('.term_content_tab .term_item:eq(' + index + ')').addClass('active').siblings().removeClass('active');
var item = host_ssh_list[data.id];
// item.term.focus();
// item.term.FitAddon.fit();
// item.resize({ cols: item.term.cols, rows: item.term.rows });
webShell_Resize();
}
});
@ -155,6 +174,8 @@ function webShell_Load(){
});
webShell_Menu();
// webShell_Resize();
// $('.term_content_tab .term-tool-button').click();
}
@ -277,11 +298,9 @@ function webShell_Menu(){
var random = 'localhost';
// host_ssh_list[random] = new Terms_WebSocketIO('#'+random, { ssh_info: { host: "38.6.224.67", ps: "22", id: random } });
host_ssh_list[random] = Terms_WebSocketIO_Create('127.0.0.1',random);
}
function webShell_openTermView(info) {
console.log(info);
if (typeof info === "undefined") {
info = { host: '127.0.0.1', ps: '本地服务器' }
}
@ -296,6 +315,8 @@ function webShell_openTermView(info) {
}
item_list.append('<span class="active item ' + (info.host == '127.0.0.1' ? 'localhost_item' : '') + '" data-host="' + info.host + '" data-id="' + random + '"><i class="icon icon-sucess"></i><div class="content"><span>' + info.ps + '</span></div><span class="icon-trem-close"></span></span>');
host_ssh_list[random] = Terms_WebSocketIO_Create(info.host, random);
webShell_Resize();
}
@ -308,6 +329,7 @@ function webShell_removeTermView(id){
try {
host_ssh_list[id].close();
} catch (error) {
console.log(error);
}
delete host_ssh_list[id];

@ -310,27 +310,29 @@ color: #bbb;
color: #4c4c4c;
}
.term_content_tab .term_item {
height: 100%;
width: 100%;
display: none;
}
.term_content_tab .term_item.active {
display: inline-block;
}
.term_content_tab {
background-color: #000;
background-color: rgb(51, 51, 51);
position: absolute;
top: 38px;
left: 0;
right: 0;
bottom: 0;
padding: 10px 5px 10px 10px;
padding: 10px 10px 10px 10px;
overflow: hidden;
}
.term_content_tab .term_item {
height: 100%;
width: 100%;
display: none;
}
.term_content_tab .term_item.active {
display: inline-block;
}
.term-tool-button {
position: absolute;
right: -7px;

@ -9,7 +9,10 @@
<div class="list">
<span class="item active" data-host="127.0.0.1" data-id="localhost">
<i class="icon-sucess icon"></i>
<div class="content"><span>本地服务器</span></div><span class="icon-trem-close"></span></span>
<div class="content">
<span>本地服务器</span>
</div>
<span class="icon-trem-close"></span>
</div>
<span class="addServer" title="添加服务器SSH信息">
<span class="glyphicon glyphicon-plus" aria-hidden="true" ></span>
@ -23,7 +26,7 @@
<!-- 控制台 -->
<div class="term_content_tab">
<div class="term-tool-button tool-hide"><span class="glyphicon glyphicon-menu-right"></span></div>
<div class="term_item" id="localhost" style="display:block;position: inherit;"></div>
<div class="term_item active" id="localhost" data-host="127.0.0.1"></div>
</div>
</div>
<div class="term_tootls">

@ -23,80 +23,91 @@ Terms_WebSocketIO.prototype = {
this.callback_close = callback;
},
// websocket持久化连接
connect: function (callback) {
connectWs: function (callback) {
if(!this.ws){
this.ws = io.connect();
}
},
//连接服务器成功
on_open: function (ws_event) {
this.term.FitAddon.fit();
this.resize({ cols: this.term.cols, rows: this.term.rows });
connectSsh:function(){
this.send(this.ssh_info);
this.send('\n');
},
close:function(){
this.ws.disconnect();
this.ws.close();
},
//服务器消息事件
on_message: function (ws_event) {
this.term.write(ws_event.data);
console.log(ws_event.data);
if (ws_event.data == '\r\n登出\r\n' || ws_event.data == '登出\r\n' ||
ws_event.data == '\r\nlogout\r\n' || ws_event.data == 'logout\r\n'||
ws_event.data == '\r\nexit\r\n' || ws_event.data == 'exit\r\n') {
this.term.destroy();
clearInterval(this.term_timer);
this.ws.disconnect();
this.ws.close();
clearInterval(this.term_timer);
console.log('message',this.callback_close,typeof(this.callback_close));
if (this.callback_close){
this.callback_close();
}
}
},
resize: function (size) {
if (this.ws) {
size['resize'] = 1;
this.send(JSON.stringify(size));
}
on_connect:function(ws_event){
},
on_exit:function(ws_event){
},
send:function(data){
this.ws.emit(this.route, data);
},
resize: function (size) {
if (this.ws) {
size['resize'] = 1;
this.send(size)
}
},
run: function (ssh_info) {
this.connect();
this.connectWs();
var that = this;
var termCols = 83;
var termRows = 21;
this.term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
this.term = new Terminal({fontSize: this.fontSize,screenKeys: true, useStyle: true});
this.term.open($('#'+this.id)[0]);
this.term.setOption('cursorBlink', true);
this.term.setOption('fontSize', this.fontSize);
// console.log(this.term.cols,this.term.rows);
// this.term.fit();
// console.log(this.term.cols,this.term.rows);
// this.term.FitAddon = new window.FitAddon();
// this.term.loadAddon(this.term.FitAddon);
// this.term.WebLinksAddon = new WebLinksAddon.WebLinksAddon();
// this.term.loadAddon(this.term.WebLinksAddon);
this.ws.on('server_response', function (ev) { that.on_message(ev)});
this.ws.on('connect', function (ev) { that.on_connect(ev)});
this.ws.on('exit', function (ev) { that.on_exit(ev)});
if (this.ws) {
that.ws.emit('webssh_websocketio', '');
that.send('');
this.term_timer = setInterval(function () {
that.ws.emit('webssh_websocketio', '');
}, 500);
that.send('');
}, 600);
}
this.term.on('data', function (data) {
that.ws.emit('webssh_websocketio', data);
try {
that.send(data)
} catch (e) {
that.term.write('\r\n连接丢失,正在尝试重新连接!\r\n');
that.connectSsh();
}
});
that.term.write('\r\n请稍等,正在链接中...\r\n');
this.ws.emit('webssh_websocketio', this.ssh_info);
this.ws.emit('webssh_websocketio', '\n');
this.connectSsh();
this.term.focus();
}
}

Loading…
Cancel
Save