diff --git a/app.py b/app.py
index 70bb36656..1c964d876 100644
--- a/app.py
+++ b/app.py
@@ -3,10 +3,12 @@
import sys
import io
import os
-from route import app
+from route import app, socketio
try:
if __name__ == "__main__":
- app.run()
+ PORT = 7200
+ HOST = '0.0.0.0'
+ socketio.run(app, host=HOST, port=PORT)
except Exception as ex:
print ex
diff --git a/class/core/public.py b/class/core/public.py
index e8e3bfa98..f219f103b 100755
--- a/class/core/public.py
+++ b/class/core/public.py
@@ -851,3 +851,34 @@ def get_string_arr(t):
if s1 == s_arr[i][j]:
t_arr.append(str(i) + str(j))
return t_arr
+
+
+def getSSHPort():
+ try:
+ file = '/etc/ssh/sshd_config'
+ conf = ReadFile(file)
+ rep = "#*Port\s+([0-9]+)\s*\n"
+ port = re.search(rep, conf).groups(0)[0]
+ return int(port)
+ except:
+ return 22
+
+
+def getSSHStatus():
+ if os.path.exists('/usr/bin/apt-get'):
+ status = execShell("service ssh status | grep -P '(dead|stop)'")
+ else:
+ import system_api
+ version = system_api.system_api().getSystemVersion()
+ if version.find(' Mac ') != -1:
+ return True
+ if version.find(' 7.') != -1:
+ status = execShell("systemctl status sshd.service | grep 'dead'")
+ else:
+ status = execShell(
+ "/etc/init.d/sshd status | grep -e 'stopped' -e '已停'")
+ if len(status[0]) > 3:
+ status = False
+ else:
+ status = True
+ return status
diff --git a/plugins/webssh/index.html b/plugins/webssh/index.html
index 6b0ad312e..a5a499950 100755
--- a/plugins/webssh/index.html
+++ b/plugins/webssh/index.html
@@ -1,14 +1,10 @@
-
\ No newline at end of file
diff --git a/plugins/webssh/js/webssh.js b/plugins/webssh/js/webssh.js
index 883064e0a..7cd01e883 100755
--- a/plugins/webssh/js/webssh.js
+++ b/plugins/webssh/js/webssh.js
@@ -1,6 +1,6 @@
-function web_shell() {
- var termCols = 100;
- var termRows = 29;
+function web_shell2() {
+ var termCols = 50;
+ var termRows = 12;
var sendTotal = 0;
if(!socket)socket = io.connect();
var term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
@@ -9,6 +9,7 @@ function web_shell() {
term.setOption('cursorBlink', true);
socket.on('server_response', function (data) {
+ console.log('server_response',data);
term.write(data.data);
if (data.data == '\r\n登出\r\n' || data.data == '登出\r\n' || data.data == '\r\nlogout\r\n' || data.data == 'logout\r\n') {
@@ -26,6 +27,7 @@ function web_shell() {
}
term.on('data', function (data) {
+ console.log('data',data);
socket.emit('webssh', data);
});
@@ -33,7 +35,7 @@ function web_shell() {
var term_box = layer.open({
type: 1,
title: "宝塔终端",
- area: ['920px','640px'],
+ area: ['480px','360px'],
closeBtn: 2,
shadeClose: false,
content: '
\
@@ -109,9 +111,6 @@ function web_shell() {
\
粘贴选中项\
\
- \
- 翻译\
- \
\
百度搜索\
\
@@ -166,17 +165,6 @@ function web_shell() {
}
-function shell_translate_text() {
- remove_ssh_menu();
- var selectText = getCookie('ssh_selection');
- var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
- $.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
- layer.close(loadT);
- layer.msg("原文: " + rdata.src + '
译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
- }, 'JSONP');
- gterm.focus();
-}
-
function shell_to_baidu() {
var selectText = getCookie('ssh_selection');
remove_ssh_menu();
diff --git a/requirements.txt b/requirements.txt
index c6b46b9c8..115efc02c 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,5 +1,6 @@
flask
flask_session
+flask_socketio
gunicorn
psutil
pillow
diff --git a/route/__init__.py b/route/__init__.py
index 4261b162b..548c3b77b 100755
--- a/route/__init__.py
+++ b/route/__init__.py
@@ -10,6 +10,7 @@ import uuid
reload(sys)
sys.setdefaultencoding('utf8')
+
from datetime import timedelta
from flask import Flask
@@ -23,18 +24,25 @@ from flask import url_for
from flask_session import Session
+
sys.path.append(os.getcwd() + "/class/core")
import db
import public
import config_api
-
app = Flask(__name__, template_folder='templates/default')
app.config.version = config_api.config_api().getVersion()
# app.config['SECRET_KEY'] = os.urandom(24)
# app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
app.config['SECRET_KEY'] = uuid.UUID(int=uuid.getnode()).hex[-12:]
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=7)
+
+# socketio
+sys.path.append("/usr/local/lib/python2.7/site-packages")
+from flask_socketio import SocketIO, emit, send
+socketio = SocketIO()
+socketio.init_app(app)
+
try:
from flask_sqlalchemy import SQLAlchemy
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:////tmp/py_mw_session.db'
@@ -195,3 +203,111 @@ def index(reqClass=None, reqAction=None, reqData=None):
eval_str = "__import__('" + className + "')." + className + '()'
newInstance = eval(eval_str)
return publicObject(newInstance, reqAction)
+
+ssh = None
+shell = None
+try:
+ import paramiko
+ ssh = paramiko.SSHClient()
+except:
+ public.execShell('pip install paramiko==2.0.2 &')
+
+
+def connect_ssh():
+ global shell, ssh
+ print 'connect_ssh'
+ ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
+ try:
+ ssh.connect('127.0.0.1', public.getSSHPort())
+ except Exception as e:
+ print 'connect_ssh:', str(e)
+ if public.getSSHStatus():
+ try:
+ ssh.connect('localhost', public.getSSHPort())
+ except:
+ return False
+ import firewalls
+ fw = firewalls.firewalls()
+ get = common.dict_obj()
+ get.status = '0'
+ fw.SetSshStatus(get)
+ ssh.connect('127.0.0.1', public.GetSSHPort())
+ get.status = '1'
+ fw.SetSshStatus(get)
+ shell = ssh.invoke_shell(term='xterm', width=100, height=29)
+ shell.setblocking(0)
+ return True
+
+
+# 取数据对象
+def get_input_data(data):
+ pdata = common.dict_obj()
+ for key in data.keys():
+ pdata[key] = str(data[key])
+ return pdata
+
+
+@socketio.on('webssh')
+def webssh(msg):
+ emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
+ print 'webssh', msg
+ if not isLogined():
+ emit('server_response', {'data': '会话丢失,请重新登陆面板!\r\n'})
+ return None
+ global shell, ssh
+ ssh_success = True
+ if not shell:
+ ssh_success = connect_ssh()
+ if not shell:
+ emit('server_response', {
+ 'data': public.getMsg('INIT_WEBSSH_CONN_ERR')})
+ return
+ if shell.exit_status_ready():
+ ssh_success = connect_ssh()
+ if not ssh_success:
+ emit('server_response', {
+ 'data': public.getMsg('INIT_WEBSSH_CONN_ERR')})
+ return
+ shell.send(msg)
+ try:
+ time.sleep(0.005)
+ recv = shell.recv(4096)
+ emit('server_response', {'data': recv.decode("utf-8")})
+ except Exception as ex:
+ pass
+
+
+@socketio.on('connect_event')
+def connected_msg(msg):
+ connect_ssh()
+ if not isLogined():
+ print 'not login'
+ emit(pdata.s_response, {'data': public.getMsg('INIT_WEBSSH_LOGOUT')})
+ return None
+ global shell, ssh
+ print 'connect_event:connected_msg', msg
+ try:
+ recv = shell.recv(8192)
+ print recv
+ print recv.decode("utf-8")
+ emit('server_response', {'data': recv.decode("utf-8")})
+ except Exception as e:
+ print 'connect_event:' + str(e)
+
+
+@socketio.on('panel')
+def websocket_test(data):
+ pdata = get_input_data(data)
+ if not isLogined():
+ emit(pdata.s_response, {
+ 'data': public.returnData(-1, '会话丢失,请重新登陆面板!\r\n')})
+ return None
+ mods = ['site', 'ftp', 'database', 'ajax', 'system', 'crontab', 'files',
+ 'config', 'panel_data', 'plugin', 'ssl', 'auth', 'firewall', 'panel_wxapp']
+ if not pdata['s_module'] in mods:
+ result = public.returnMsg(False, "INIT_WEBSOCKET_ERR")
+ else:
+ result = eval("%s(pdata)" % pdata['s_module'])
+ if not hasattr(pdata, 's_response'):
+ pdata.s_response = 'response'
+ emit(pdata.s_response, {'data': result})
diff --git a/route/static/app/public.js b/route/static/app/public.js
index 9495a9789..f49081f26 100755
--- a/route/static/app/public.js
+++ b/route/static/app/public.js
@@ -1201,12 +1201,14 @@ function loadImage(){
});
}
-
+var socket, gterm;
function webShell() {
- var termCols = 100;
- var termRows = 29;
+ var termCols = 50;
+ var termRows = 12;
var sendTotal = 0;
- if(!socket)socket = io.connect();
+ if(!socket){
+ socket = io.connect();
+ }
var term = new Terminal({ cols: termCols, rows: termRows, screenKeys: true, useStyle: true});
term.open();
gterm = term
@@ -1236,8 +1238,8 @@ function webShell() {
var term_box = layer.open({
type: 1,
- title: "宝塔终端",
- area: ['920px','640px'],
+ title: "本地终端",
+ area: ['480px','300px'],
closeBtn: 2,
shadeClose: false,
content: '\
@@ -1307,18 +1309,9 @@ function webShell() {
var menudiv = '';
$("body").append(menudiv);
$(".contextmenu").css({
@@ -1370,16 +1363,16 @@ function webShell() {
}
-function shell_translate_text() {
- remove_ssh_menu();
- var selectText = getCookie('ssh_selection');
- var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
- $.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
- layer.close(loadT);
- layer.msg("原文: " + rdata.src + '
译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
- }, 'JSONP');
- gterm.focus();
-}
+// function shell_translate_text() {
+// remove_ssh_menu();
+// var selectText = getCookie('ssh_selection');
+// var loadT = layer.msg('正在翻译...', { icon: 16, time: 1000 * 60, });
+// $.get('https://www.bt.cn/api/index/fanyi', { query: selectText }, function (rdata) {
+// layer.close(loadT);
+// layer.msg("原文: " + rdata.src + '
译文: ' + rdata.dst, { time: 1000 * 10, shadeClose: true, shade: 0.01 });
+// }, 'JSONP');
+// gterm.focus();
+// }
function shell_to_baidu() {
var selectText = getCookie('ssh_selection');
diff --git a/route/static/css/site.css b/route/static/css/site.css
index ee1858cf4..20c12694f 100755
--- a/route/static/css/site.css
+++ b/route/static/css/site.css
@@ -4646,4 +4646,34 @@ select[disabled]{
}
.btswitch-btn.bt-waf-firewall{
width:2.4em;height:1.4em;margin-bottom: 0
-}
\ No newline at end of file
+}
+
+
+/*6.0终端样式*/
+.term-box{
+ padding:0 10px 10px;
+ background-color:#333333;
+}
+.shell-text-input .bt-input-text-shell{
+ width:100%;
+ padding:10px 10px 0;
+ border:0 none;
+ height:60px;
+ overflow:auto;
+ resize:none;
+}
+.shell-text-input .bt-input-text-shell:focus,.shell-text-input .bt-input-text-shell:active{
+ border:0 none;
+ outline:none;
+}
+.shell-btn-group{
+ height:30px;
+ position:absolute;
+ bottom:10px;
+ right:10px;
+}
+.shell_btn_close{
+ margin-right:8px;
+}
+
+
diff --git a/route/templates/default/layout.html b/route/templates/default/layout.html
index f2370723c..ed1c744c4 100755
--- a/route/templates/default/layout.html
+++ b/route/templates/default/layout.html
@@ -39,15 +39,23 @@
+
+
+
+
+
+
+
+
-
-
+
+
{% block content %}{% endblock %}