mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-10 01:39:25 +08:00
update
This commit is contained in:
@@ -185,3 +185,4 @@ plugins/goedge-node
|
|||||||
plugins/goedge-happy
|
plugins/goedge-happy
|
||||||
plugins/dztasks
|
plugins/dztasks
|
||||||
|
|
||||||
|
data/default_new.pl
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class config_api:
|
|||||||
'bind_domain' : 'data/bind_domain.pl', # 面板域名绑定
|
'bind_domain' : 'data/bind_domain.pl', # 面板域名绑定
|
||||||
'unauth_status' : 'data/unauthorized_status.pl', # URL路径未成功显示状态
|
'unauth_status' : 'data/unauthorized_status.pl', # URL路径未成功显示状态
|
||||||
'auth_secret': 'data/auth_secret.pl', # 二次验证密钥
|
'auth_secret': 'data/auth_secret.pl', # 二次验证密钥
|
||||||
'ssl':'ssl/choose.pl', # ssl设置
|
'ssl':'ssl/choose.pl', # ssl设置
|
||||||
'hook_database' : 'data/hook_database.json', # 数据库钩子
|
'hook_database' : 'data/hook_database.json', # 数据库钩子
|
||||||
'hook_menu' : 'data/hook_menu.json', # 菜单钩子
|
'hook_menu' : 'data/hook_menu.json', # 菜单钩子
|
||||||
'hook_global_static' : 'data/hook_global_static.json', # 静态文件钩子
|
'hook_global_static' : 'data/hook_global_static.json', # 静态文件钩子
|
||||||
|
|||||||
@@ -717,7 +717,6 @@ class system_api:
|
|||||||
|
|
||||||
self.cache[iokey] = {'info':diskio_group,'time':mtime}
|
self.cache[iokey] = {'info':diskio_group,'time':mtime}
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# print(mw.getTracebackInfo())
|
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return diskInfo
|
return diskInfo
|
||||||
|
|||||||
@@ -220,7 +220,7 @@ def getDbConfValue():
|
|||||||
rep_scope = r"\[database\](.*?)\["
|
rep_scope = r"\[database\](.*?)\["
|
||||||
tmp = re.findall(rep_scope, content, re.S)
|
tmp = re.findall(rep_scope, content, re.S)
|
||||||
|
|
||||||
rep = '(\w*)\s*=\s*(.*)'
|
rep = '(\\w*)\\s*=\\s*(.*)'
|
||||||
tmp = re.findall(rep, tmp[0])
|
tmp = re.findall(rep, tmp[0])
|
||||||
r = {}
|
r = {}
|
||||||
for x in range(len(tmp)):
|
for x in range(len(tmp)):
|
||||||
|
|||||||
+35
-4
@@ -8,7 +8,11 @@
|
|||||||
# Author: midoks <midoks@163.com>
|
# Author: midoks <midoks@163.com>
|
||||||
# ---------------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
import uuid
|
||||||
|
import logging
|
||||||
|
from datetime import timedelta
|
||||||
|
|
||||||
from flask import Flask
|
from flask import Flask
|
||||||
from flask_socketio import SocketIO, emit, send
|
from flask_socketio import SocketIO, emit, send
|
||||||
@@ -20,6 +24,7 @@ from flask_migrate import Migrate
|
|||||||
from werkzeug.local import LocalProxy
|
from werkzeug.local import LocalProxy
|
||||||
|
|
||||||
from admin.model import db as sys_db
|
from admin.model import db as sys_db
|
||||||
|
from admin import setup
|
||||||
|
|
||||||
import core.mw as mw
|
import core.mw as mw
|
||||||
import setting
|
import setting
|
||||||
@@ -33,25 +38,46 @@ socketio = SocketIO(manage_session=False, async_mode='threading',
|
|||||||
|
|
||||||
app = Flask(__name__, template_folder='templates/default')
|
app = Flask(__name__, template_folder='templates/default')
|
||||||
|
|
||||||
|
# app.debug = True
|
||||||
|
|
||||||
# 静态文件配置
|
# 静态文件配置
|
||||||
from whitenoise import WhiteNoise
|
from whitenoise import WhiteNoise
|
||||||
app.wsgi_app = WhiteNoise(app.wsgi_app, root="../web/static/", prefix="static/", max_age=604800)
|
app.wsgi_app = WhiteNoise(app.wsgi_app, root="../web/static/", prefix="static/", max_age=604800)
|
||||||
|
|
||||||
|
# session配置
|
||||||
|
app.secret_key = uuid.UUID(int=uuid.getnode()).hex[-12:]
|
||||||
|
# app.config['sessions'] = dict()
|
||||||
|
app.config['SESSION_PERMANENT'] = True
|
||||||
|
app.config['SESSION_USE_SIGNER'] = True
|
||||||
|
app.config['SESSION_KEY_PREFIX'] = 'MW_:'
|
||||||
|
app.config['SESSION_COOKIE_NAME'] = "MW_VER_1"
|
||||||
|
app.config['PERMANENT_SESSION_LIFETIME'] = timedelta(days=31)
|
||||||
|
|
||||||
# db的配置
|
# db的配置
|
||||||
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///'+root_dir+'/example.log' # 使用 SQLite 数据库
|
app.config['SQLALCHEMY_DATABASE_URI'] = mw.getSqitePrefix()+setting.SQLITE_PATH # 使用 SQLite 数据库
|
||||||
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
|
||||||
|
|
||||||
|
|
||||||
# 初始化db
|
# 初始化db
|
||||||
sys_db.init_app(app)
|
sys_db.init_app(app)
|
||||||
Migrate(app, sys_db)
|
Migrate(app, sys_db)
|
||||||
|
|
||||||
|
# 检查数据库是否存在。如果没有就创建它。
|
||||||
|
setup_db_required = False
|
||||||
|
if not os.path.isfile(setting.SQLITE_PATH):
|
||||||
|
setup_db_required = True
|
||||||
|
|
||||||
|
# with app.app_context():
|
||||||
|
# sys_db.create_all()
|
||||||
|
|
||||||
with app.app_context():
|
with app.app_context():
|
||||||
sys_db.create_all()
|
if setup_db_required:
|
||||||
|
sys_db.create_all()
|
||||||
|
|
||||||
|
# 初始化用户信息
|
||||||
|
with app.app_context():
|
||||||
|
setup.init_admin_user()
|
||||||
|
|
||||||
# print(mw.getRunDir())
|
|
||||||
# print(app.config['SQLALCHEMY_DATABASE_URI'])
|
|
||||||
|
|
||||||
|
|
||||||
# 加载模块
|
# 加载模块
|
||||||
@@ -61,6 +87,9 @@ for module in get_submodules():
|
|||||||
if app.blueprints.get(module.name) is None:
|
if app.blueprints.get(module.name) is None:
|
||||||
app.register_blueprint(module)
|
app.register_blueprint(module)
|
||||||
|
|
||||||
|
@app.before_request
|
||||||
|
def requestCheck():
|
||||||
|
print("hh")
|
||||||
|
|
||||||
@app.after_request
|
@app.after_request
|
||||||
def requestAfter(response):
|
def requestAfter(response):
|
||||||
@@ -127,6 +156,8 @@ def inject_global_variables():
|
|||||||
# return jsonify(result)
|
# return jsonify(result)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Log the startup
|
# Log the startup
|
||||||
app.logger.info('########################################################')
|
app.logger.info('########################################################')
|
||||||
app.logger.info('Starting %s v%s...', setting.APP_NAME, setting.APP_VERSION)
|
app.logger.info('Starting %s v%s...', setting.APP_NAME, setting.APP_VERSION)
|
||||||
|
|||||||
@@ -10,13 +10,38 @@
|
|||||||
|
|
||||||
|
|
||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template
|
||||||
|
from flask import request,g
|
||||||
|
|
||||||
blueprint = Blueprint('dashboard', __name__, url_prefix='/', template_folder='../../templates/default')
|
import core.mw as mw
|
||||||
|
|
||||||
|
blueprint = Blueprint('dashboard', __name__, url_prefix='/', template_folder='../../templates')
|
||||||
@blueprint.route('/')
|
@blueprint.route('/')
|
||||||
def index():
|
def index():
|
||||||
return render_template('index.html', data = {})
|
return render_template('default/index.html', data = {})
|
||||||
|
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# 定义登录入口相关方法
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@blueprint.route('/login')
|
||||||
|
def login():
|
||||||
|
return render_template('default/login.html', data = {})
|
||||||
|
|
||||||
|
# 检查是否登录
|
||||||
@blueprint.route('/check_login',methods=['GET','POST'])
|
@blueprint.route('/check_login',methods=['GET','POST'])
|
||||||
def check_login():
|
def check_login():
|
||||||
return "0"
|
return "0"
|
||||||
|
|
||||||
|
# 执行登录操作
|
||||||
|
@blueprint.route('/do_login', endpoint='do_login', methods=['POST'])
|
||||||
|
def do_login():
|
||||||
|
|
||||||
|
username = request.form.get('username', '').strip()
|
||||||
|
password = request.form.get('password', '').strip()
|
||||||
|
code = request.form.get('code', '').strip()
|
||||||
|
|
||||||
|
print(g)
|
||||||
|
print(username, password, code )
|
||||||
|
|
||||||
|
return mw.returnData(False, '面板已经关闭!')
|
||||||
|
|||||||
@@ -11,7 +11,22 @@
|
|||||||
|
|
||||||
from flask import Blueprint, render_template
|
from flask import Blueprint, render_template
|
||||||
|
|
||||||
blueprint = Blueprint('logs', __name__, url_prefix='/logs', template_folder='../../templates/default')
|
from admin.user_login_check import panel_login_required
|
||||||
|
|
||||||
|
blueprint = Blueprint('logs', __name__, url_prefix='/logs', template_folder='../../templates')
|
||||||
@blueprint.route('/index', endpoint='index')
|
@blueprint.route('/index', endpoint='index')
|
||||||
def index():
|
def index():
|
||||||
return render_template('logs.html', data={})
|
return render_template('default/logs.html', data={})
|
||||||
|
|
||||||
|
|
||||||
|
# 日志列表
|
||||||
|
@blueprint.route('/get_log_list', endpoint='get_log_list', methods=['POST'])
|
||||||
|
@panel_login_required
|
||||||
|
def get_log_list():
|
||||||
|
return []
|
||||||
|
|
||||||
|
# 审计日志列表
|
||||||
|
@blueprint.route('/get_audit_logs_files', endpoint='get_audit_logs_files', methods=['POST'])
|
||||||
|
@panel_login_required
|
||||||
|
def get_audit_logs_files():
|
||||||
|
return []
|
||||||
+91
-10
@@ -17,11 +17,11 @@ SCHEMA_VERSION = 1
|
|||||||
|
|
||||||
|
|
||||||
db = SQLAlchemy(
|
db = SQLAlchemy(
|
||||||
engine_options={
|
engine_options={
|
||||||
'pool_size': setting.CONFIG_DATABASE_CONNECTION_POOL_SIZE,
|
'pool_size': setting.CONFIG_DATABASE_CONNECTION_POOL_SIZE,
|
||||||
'max_overflow': setting.CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW
|
'max_overflow': setting.CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class Version(db.Model):
|
class Version(db.Model):
|
||||||
@@ -42,11 +42,12 @@ class Option(db.Model):
|
|||||||
__tablename__ = 'option'
|
__tablename__ = 'option'
|
||||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
name = db.Column(db.String(128), unique=True, nullable=False, comment="配置名称")
|
name = db.Column(db.String(128), unique=True, nullable=False, comment="配置名称")
|
||||||
|
type = db.Column(db.String(50), unique=False, nullable=False, default='common',comment="计划类型:common/hook/web")
|
||||||
value = db.Column(db.TEXT, unique=False, nullable=False, comment="内容")
|
value = db.Column(db.TEXT, unique=False, nullable=False, comment="内容")
|
||||||
|
|
||||||
class User(db.Model):
|
class Users(db.Model):
|
||||||
"""定义登录用户"""
|
"""定义登录用户"""
|
||||||
__tablename__ = 'user'
|
__tablename__ = 'users'
|
||||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
name = db.Column(db.String(128), unique=True, nullable=False, comment="用户名")
|
name = db.Column(db.String(128), unique=True, nullable=False, comment="用户名")
|
||||||
password = db.Column(db.String(128), unique=False, nullable=False, comment="密码")
|
password = db.Column(db.String(128), unique=False, nullable=False, comment="密码")
|
||||||
@@ -54,6 +55,8 @@ class User(db.Model):
|
|||||||
login_time = db.Column(db.String(128), unique=False, nullable=True, comment="登录时间")
|
login_time = db.Column(db.String(128), unique=False, nullable=True, comment="登录时间")
|
||||||
phone = db.Column(db.String(20), unique=False, nullable=False,comment="手机")
|
phone = db.Column(db.String(20), unique=False, nullable=False,comment="手机")
|
||||||
email = db.Column(db.String(320), nullable=False, comment="邮件")
|
email = db.Column(db.String(320), nullable=False, comment="邮件")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||||
|
|
||||||
class Crontab(db.Model):
|
class Crontab(db.Model):
|
||||||
"""定义计划任务"""
|
"""定义计划任务"""
|
||||||
@@ -73,7 +76,7 @@ class Crontab(db.Model):
|
|||||||
save = db.Column(db.Integer, unique=False, nullable=True, default=3,comment="备份数量")
|
save = db.Column(db.Integer, unique=False, nullable=True, default=3,comment="备份数量")
|
||||||
status = db.Column(db.Integer, unique=False, nullable=True, default=1, comment="状态")
|
status = db.Column(db.Integer, unique=False, nullable=True, default=1, comment="状态")
|
||||||
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
update_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||||
|
|
||||||
class Logs(db.Model):
|
class Logs(db.Model):
|
||||||
"""定义日志"""
|
"""定义日志"""
|
||||||
@@ -88,8 +91,8 @@ class Firewall(db.Model):
|
|||||||
"""定义防火墙"""
|
"""定义防火墙"""
|
||||||
__tablename__ = 'firewall'
|
__tablename__ = 'firewall'
|
||||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
port = db.Column(db.Integer(), unique=True, nullable=False, comment="端口")
|
port = db.Column(db.Integer(), unique=False, nullable=False, comment="端口")
|
||||||
protocol = db.Column(db.Integer(), unique=True, nullable=False, comment="协议/tcp/udp")
|
protocol = db.Column(db.Integer(), unique=False, nullable=False, comment="协议/tcp/udp")
|
||||||
ps = db.Column(db.TEXT, unique=False, nullable=False, comment="备注")
|
ps = db.Column(db.TEXT, unique=False, nullable=False, comment="备注")
|
||||||
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||||
@@ -106,6 +109,84 @@ class Backup(db.Model):
|
|||||||
size = db.Column(db.Integer(), unique=False, nullable=False, comment="大小")
|
size = db.Column(db.Integer(), unique=False, nullable=False, comment="大小")
|
||||||
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
class Sites(db.Model):
|
||||||
|
"""定义计划任务"""
|
||||||
|
__tablename__ = 'sites'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
name = db.Column(db.TEXT, unique=False, nullable=False, comment="网站名称")
|
||||||
|
path = db.Column(db.TEXT, unique=False, nullable=False, comment="网站路径")
|
||||||
|
index = db.Column(db.TEXT, unique=False, nullable=False, comment="")
|
||||||
|
ps = db.Column(db.TEXT, unique=False, nullable=False, comment="备注")
|
||||||
|
edate = db.Column(db.TEXT, unique=False, nullable=False, comment="到期时间")
|
||||||
|
type_id = db.Column(db.TEXT, unique=False, nullable=False, comment="分类ID")
|
||||||
|
status = db.Column(db.Integer(), unique=False, nullable=True, default=1, comment="状态")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||||
|
|
||||||
|
class SiteType(db.Model):
|
||||||
|
"""定义站点类型"""
|
||||||
|
__tablename__ = 'site_type'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
name = db.Column(db.TEXT, unique=False, nullable=False, comment="类型名称")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||||
|
|
||||||
|
class Domain(db.Model):
|
||||||
|
"""定义站点域名"""
|
||||||
|
__tablename__ = 'domain'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
pid = db.Column(db.Integer(), unique=False, nullable=False, comment="站点ID")
|
||||||
|
name = db.Column(db.TEXT, unique=False, nullable=False, comment="域名")
|
||||||
|
port = db.Column(db.Integer(), unique=False, nullable=False, comment="端口")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
class Binding(db.Model):
|
||||||
|
"""定义站点绑定"""
|
||||||
|
__tablename__ = 'binding'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
pid = db.Column(db.Integer(), unique=False, nullable=False, comment="站点ID")
|
||||||
|
domain = db.Column(db.TEXT, unique=False, nullable=False, comment="域名")
|
||||||
|
path = db.Column(db.TEXT, unique=False, nullable=False, comment="路径")
|
||||||
|
port = db.Column(db.Integer(), unique=False, nullable=False, comment="端口")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
|
||||||
|
class Tasks(db.Model):
|
||||||
|
"""定义任务"""
|
||||||
|
__tablename__ = 'tasks'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
name = db.Column(db.TEXT, unique=False, nullable=False, comment="任务名称")
|
||||||
|
type = db.Column(db.TEXT, unique=False, nullable=False, comment="域名")
|
||||||
|
execstr = db.Column(db.TEXT, unique=False, nullable=False, comment="返回内容")
|
||||||
|
start = db.Column(db.Integer(), unique=False, nullable=True, comment="开始执行时间")
|
||||||
|
end = db.Column(db.Integer(), unique=False, nullable=True, comment="结束执行时间")
|
||||||
|
status = db.Column(db.Integer(), unique=False, nullable=True, default=1, comment="状态")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
|
||||||
|
class TempLogin(db.Model):
|
||||||
|
"""定义临时登录"""
|
||||||
|
__tablename__ = 'temp_login'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
token = db.Column(db.TEXT, unique=False, nullable=False, comment="token")
|
||||||
|
salt = db.Column(db.TEXT, unique=False, nullable=False, comment="salt")
|
||||||
|
state = db.Column(db.Integer(), unique=False, nullable=False, comment="状态")
|
||||||
|
login_time = db.Column(db.Integer(), unique=False, nullable=True, comment="登录时间")
|
||||||
|
login_addr = db.Column(db.Integer(), unique=False, nullable=True, comment="登录地址")
|
||||||
|
logout_time = db.Column(db.Integer(), unique=False, nullable=True, comment="登出时间")
|
||||||
|
expire = db.Column(db.Integer(), unique=False, nullable=True, comment="过期时间")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
class Panel(db.Model):
|
||||||
|
"""定义其他面板"""
|
||||||
|
__tablename__ = 'panel'
|
||||||
|
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||||
|
title = db.Column(db.TEXT, unique=False, nullable=False, comment="标题")
|
||||||
|
url = db.Column(db.TEXT, unique=False, nullable=False, comment="地址")
|
||||||
|
username = db.Column(db.Integer(), unique=False, nullable=False, comment="用户名")
|
||||||
|
password = db.Column(db.Integer(), unique=False, nullable=True, comment="密码")
|
||||||
|
click = db.Column(db.Integer(), unique=False, nullable=True, comment="点击次数")
|
||||||
|
add_time = db.Column(db.TEXT, nullable=False, comment="添加时间")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ def index():
|
|||||||
|
|
||||||
# 初始化检查,首页提示选择安装
|
# 初始化检查,首页提示选择安装
|
||||||
@blueprint.route('/init', endpoint='init', methods=['POST'])
|
@blueprint.route('/init', endpoint='init', methods=['POST'])
|
||||||
|
@panel_login_required
|
||||||
def init():
|
def init():
|
||||||
plugin_names = {
|
plugin_names = {
|
||||||
'openresty': '1.25.3',
|
'openresty': '1.25.3',
|
||||||
@@ -38,6 +39,13 @@ def init():
|
|||||||
}
|
}
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
# 首页软件展示
|
||||||
|
@blueprint.route('/index_list', endpoint='index_list', methods=['GET','POST'])
|
||||||
|
@panel_login_required
|
||||||
|
def index_list():
|
||||||
|
pg = MwPlugin.instance()
|
||||||
|
return pg.getIndexList()
|
||||||
|
|
||||||
# 插件列表
|
# 插件列表
|
||||||
@blueprint.route('/list', endpoint='list', methods=['GET'])
|
@blueprint.route('/list', endpoint='list', methods=['GET'])
|
||||||
@panel_login_required
|
@panel_login_required
|
||||||
@@ -102,7 +110,6 @@ def run():
|
|||||||
|
|
||||||
pg = MwPlugin.instance()
|
pg = MwPlugin.instance()
|
||||||
data = pg.run(name, func, version, args, script)
|
data = pg.run(name, func, version, args, script)
|
||||||
|
|
||||||
if data[1] == '':
|
if data[1] == '':
|
||||||
r = mw.returnData(True, "OK", data[0].strip())
|
r = mw.returnData(True, "OK", data[0].strip())
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -0,0 +1,11 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from .user import *
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
from admin.model import db, Users
|
||||||
|
|
||||||
|
import core.mw as mw
|
||||||
|
|
||||||
|
# 初始化用户信息
|
||||||
|
def init_admin_user():
|
||||||
|
data = Users.query.filter_by(id=1).first()
|
||||||
|
if not data:
|
||||||
|
name = mw.getRandomString(8).lower()
|
||||||
|
password = mw.getRandomString(8).lower()
|
||||||
|
file_pass_pl = mw.getPanelDataDir() + '/default_new.pl'
|
||||||
|
mw.writeFile(file_pass_pl, password)
|
||||||
|
insert_time = mw.formatDate()
|
||||||
|
login_ip = '127.0.0.1'
|
||||||
|
add_user = Users(
|
||||||
|
name=name,
|
||||||
|
password=mw.md5(password),
|
||||||
|
login_ip=login_ip,
|
||||||
|
login_time=insert_time,
|
||||||
|
phone='',
|
||||||
|
email='',
|
||||||
|
add_time=insert_time,
|
||||||
|
update_time=insert_time)
|
||||||
|
db.session.add(add_user)
|
||||||
|
db.session.commit()
|
||||||
|
db.session.close()
|
||||||
|
return True
|
||||||
@@ -20,6 +20,7 @@ from .plugins import blueprint as PluginsModule
|
|||||||
from .crontab import blueprint as CrontabModule
|
from .crontab import blueprint as CrontabModule
|
||||||
from .firewall import blueprint as FirewallModule
|
from .firewall import blueprint as FirewallModule
|
||||||
from .control import blueprint as ControlModule
|
from .control import blueprint as ControlModule
|
||||||
|
from .system import blueprint as SystemModule
|
||||||
|
|
||||||
def get_submodules():
|
def get_submodules():
|
||||||
return [
|
return [
|
||||||
@@ -33,5 +34,6 @@ def get_submodules():
|
|||||||
CrontabModule,
|
CrontabModule,
|
||||||
FirewallModule,
|
FirewallModule,
|
||||||
ControlModule,
|
ControlModule,
|
||||||
|
SystemModule,
|
||||||
ConfigModule,
|
ConfigModule,
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -0,0 +1,58 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
from flask import Blueprint, render_template
|
||||||
|
from flask import request
|
||||||
|
|
||||||
|
import core.mw as mw
|
||||||
|
import utils.system as sys
|
||||||
|
|
||||||
|
blueprint = Blueprint('system', __name__, url_prefix='/system', template_folder='../../templates')
|
||||||
|
|
||||||
|
# 取系统的统计信息
|
||||||
|
@blueprint.route('/system_total', endpoint='system_total')
|
||||||
|
def system_total():
|
||||||
|
data = sys.getMemInfo()
|
||||||
|
cpu = sys.getCpuInfo(interval=1)
|
||||||
|
data['cpuNum'] = cpu[1]
|
||||||
|
data['cpuRealUsed'] = cpu[0]
|
||||||
|
data['time'] = sys.getBootTime()
|
||||||
|
data['system'] = sys.getSystemVersion()
|
||||||
|
data['version'] = '0.0.1'
|
||||||
|
return data
|
||||||
|
|
||||||
|
# 取系统的网络流量信息
|
||||||
|
@blueprint.route('/network', endpoint='network')
|
||||||
|
def network():
|
||||||
|
stat = {}
|
||||||
|
stat['cpu'] = sys.getCpuInfo()
|
||||||
|
stat['load'] = sys.getLoadAverage()
|
||||||
|
stat['mem'] = sys.getMemInfo()
|
||||||
|
stat['iostat'] = sys.stats().disk()
|
||||||
|
stat['network'] = sys.stats().network()
|
||||||
|
return stat
|
||||||
|
|
||||||
|
# 取系统的磁盘信息
|
||||||
|
@blueprint.route('/disk_info', endpoint='disk_info')
|
||||||
|
def disk_info():
|
||||||
|
data = sys.getDiskInfo()
|
||||||
|
return data
|
||||||
|
|
||||||
|
# 升级检测
|
||||||
|
@blueprint.route('/update_server', endpoint='update_server')
|
||||||
|
def update_server():
|
||||||
|
panel_type = request.args.get('type', 'check')
|
||||||
|
version = request.args.get('version', '')
|
||||||
|
|
||||||
|
return mw.returnData(False, '已经是最新,无需更新!')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -11,10 +11,9 @@
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
def panel_login_required(func):
|
def panel_login_required(func):
|
||||||
|
|
||||||
print('panel_login_required',func)
|
|
||||||
|
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapper(*args, **kwargs):
|
def wrapper(*args, **kwargs):
|
||||||
|
print('panel_login_required', args, kwargs)
|
||||||
return func(*args, **kwargs)
|
return func(*args, **kwargs)
|
||||||
return wrapper
|
return wrapper
|
||||||
@@ -14,5 +14,8 @@
|
|||||||
APP_NAME = 'mdserver-web'
|
APP_NAME = 'mdserver-web'
|
||||||
APP_ICON = 'icon'
|
APP_ICON = 'icon'
|
||||||
|
|
||||||
|
APP_LOG_NAME = 'panel'
|
||||||
|
APP_SQLITE_NAME = 'panel'
|
||||||
|
|
||||||
# Copyright string for display in the app
|
# Copyright string for display in the app
|
||||||
APP_COPYRIGHT = 'Copyright (C) 2018-∞ All rights reserved.'
|
APP_COPYRIGHT = 'Copyright (C) 2018-∞ All rights reserved.'
|
||||||
+83
-2
@@ -116,11 +116,11 @@ def getUniqueId():
|
|||||||
return unique_id
|
return unique_id
|
||||||
|
|
||||||
def returnData(status, msg, data=None):
|
def returnData(status, msg, data=None):
|
||||||
|
if data == None:
|
||||||
|
return {'status': status, 'msg': msg}
|
||||||
return {'status': status, 'msg': msg, 'data': data}
|
return {'status': status, 'msg': msg, 'data': data}
|
||||||
|
|
||||||
def returnJson(status, msg, data=None):
|
def returnJson(status, msg, data=None):
|
||||||
if data == None:
|
|
||||||
return getJson({'status': status, 'msg': msg})
|
|
||||||
return getJson({'status': status, 'msg': msg, 'data': data})
|
return getJson({'status': status, 'msg': msg, 'data': data})
|
||||||
|
|
||||||
def readFile(filename):
|
def readFile(filename):
|
||||||
@@ -163,6 +163,52 @@ def systemdCfgDir():
|
|||||||
# local test
|
# local test
|
||||||
return "/tmp"
|
return "/tmp"
|
||||||
|
|
||||||
|
|
||||||
|
def formatDate(format="%Y-%m-%d %H:%M:%S", times=None):
|
||||||
|
# 格式化指定时间戳
|
||||||
|
if not times:
|
||||||
|
times = int(time.time())
|
||||||
|
time_local = time.localtime(times)
|
||||||
|
return time.strftime(format, time_local)
|
||||||
|
|
||||||
|
|
||||||
|
def strfToTime(sdate):
|
||||||
|
# 转换时间
|
||||||
|
import time
|
||||||
|
return time.strftime('%Y-%m-%d', time.strptime(sdate, '%b %d %H:%M:%S %Y %Z'))
|
||||||
|
|
||||||
|
|
||||||
|
def md5(content):
|
||||||
|
# 生成MD5
|
||||||
|
try:
|
||||||
|
m = hashlib.md5()
|
||||||
|
m.update(content.encode("utf-8"))
|
||||||
|
return m.hexdigest()
|
||||||
|
except Exception as ex:
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def getFileMd5(filename):
|
||||||
|
# 文件的MD5值
|
||||||
|
if not os.path.isfile(filename):
|
||||||
|
return False
|
||||||
|
|
||||||
|
myhash = hashlib.md5()
|
||||||
|
f = file(filename, 'rb')
|
||||||
|
while True:
|
||||||
|
b = f.read(8096)
|
||||||
|
if not b:
|
||||||
|
break
|
||||||
|
myhash.update(b)
|
||||||
|
f.close()
|
||||||
|
return myhash.hexdigest()
|
||||||
|
|
||||||
|
|
||||||
|
def getClientIp():
|
||||||
|
from flask import request
|
||||||
|
return request.remote_addr.replace('::ffff:', '')
|
||||||
|
|
||||||
|
|
||||||
def getJson(data):
|
def getJson(data):
|
||||||
import json
|
import json
|
||||||
return json.dumps(data)
|
return json.dumps(data)
|
||||||
@@ -240,6 +286,41 @@ def getSqitePrefix():
|
|||||||
prefix = 'sqlite:////'
|
prefix = 'sqlite:////'
|
||||||
return prefix
|
return prefix
|
||||||
|
|
||||||
|
def getCpuType():
|
||||||
|
cpuType = ''
|
||||||
|
if isAppleSystem():
|
||||||
|
cmd = "system_profiler SPHardwareDataType | grep 'Processor Name' | awk -F ':' '{print $2}'"
|
||||||
|
cpuinfo = execShell(cmd)
|
||||||
|
return cpuinfo[0].strip()
|
||||||
|
|
||||||
|
current_os = getOs()
|
||||||
|
if current_os.startswith('freebsd'):
|
||||||
|
cmd = "sysctl -a | egrep -i 'hw.model' | awk -F ':' '{print $2}'"
|
||||||
|
cpuinfo = execShell(cmd)
|
||||||
|
return cpuinfo[0].strip()
|
||||||
|
|
||||||
|
# 取CPU类型
|
||||||
|
cpuinfo = open('/proc/cpuinfo', 'r').read()
|
||||||
|
rep = "model\\s+name\\s+:\\s+(.+)"
|
||||||
|
tmp = re.search(rep, cpuinfo, re.I)
|
||||||
|
if tmp:
|
||||||
|
cpuType = tmp.groups()[0]
|
||||||
|
else:
|
||||||
|
cpuinfo = execShell('LANG="en_US.UTF-8" && lscpu')[0]
|
||||||
|
rep = "Model\\s+name:\\s+(.+)"
|
||||||
|
tmp = re.search(rep, cpuinfo, re.I)
|
||||||
|
if tmp:
|
||||||
|
cpuType = tmp.groups()[0]
|
||||||
|
return cpuType
|
||||||
|
|
||||||
|
|
||||||
|
def getInfo(msg, args=()):
|
||||||
|
# 取提示消息
|
||||||
|
for i in range(len(args)):
|
||||||
|
rep = '{' + str(i + 1) + '}'
|
||||||
|
msg = msg.replace(rep, args[i])
|
||||||
|
return msg
|
||||||
|
|
||||||
def getLastLine(path, num, p=1):
|
def getLastLine(path, num, p=1):
|
||||||
pyVersion = sys.version_info[0]
|
pyVersion = sys.version_info[0]
|
||||||
try:
|
try:
|
||||||
|
|||||||
+28
-1
@@ -18,7 +18,9 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from branding import APP_NAME, APP_ICON, APP_COPYRIGHT
|
import core.mw as mw
|
||||||
|
|
||||||
|
from branding import APP_NAME, APP_ICON, APP_COPYRIGHT, APP_LOG_NAME, APP_SQLITE_NAME
|
||||||
from version import APP_VERSION, APP_RELEASE, APP_REVISION, APP_SUFFIX
|
from version import APP_VERSION, APP_RELEASE, APP_REVISION, APP_SUFFIX
|
||||||
|
|
||||||
DEBUG = False
|
DEBUG = False
|
||||||
@@ -28,6 +30,31 @@ CONFIG_DATABASE_CONNECTION_POOL_SIZE = 5
|
|||||||
# 允许溢出超过连接池大小的连接数
|
# 允许溢出超过连接池大小的连接数
|
||||||
CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW = 100
|
CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW = 100
|
||||||
|
|
||||||
|
# 应用程序日志级别-其中之一:
|
||||||
|
# CRITICAL 50
|
||||||
|
# ERROR 40
|
||||||
|
# WARNING 30
|
||||||
|
# SQL 25
|
||||||
|
# INFO 20
|
||||||
|
# DEBUG 10
|
||||||
|
# NOTSET 0
|
||||||
|
CONSOLE_LOG_LEVEL = logging.WARNING
|
||||||
|
FILE_LOG_LEVEL = logging.WARNING
|
||||||
|
|
||||||
|
DATA_DIR = mw.getPanelDataDir()
|
||||||
|
|
||||||
|
# 日志文件名。这将进入数据目录,服务器模式下的非Windows平台除外。
|
||||||
|
LOG_FILE = os.path.join(mw.getMWLogs(), APP_LOG_NAME + '.log')
|
||||||
|
|
||||||
|
# 日志旋转设置日志文件将根据LOG_ROTATION_SIZE和LOG_ROTATION_AGE的值进行切换。
|
||||||
|
# 旋转的文件将以格式命名Y-m-d_H-M-S
|
||||||
|
LOG_ROTATION_SIZE = 10 # MBs
|
||||||
|
LOG_ROTATION_AGE = 1440 # minutes
|
||||||
|
LOG_ROTATION_MAX_LOG_FILES = 90 # 要保留的最大备份数
|
||||||
|
|
||||||
|
# 用于存储用户帐户和设置的SQLite数据库的默认路径。
|
||||||
|
# 此默认设置将文件放置在与此相同的目录中 配置文件,但会生成一个在整个应用程序中使用的绝对路径。
|
||||||
|
SQLITE_PATH = os.path.join(DATA_DIR, APP_SQLITE_NAME + '.db')
|
||||||
|
|
||||||
|
|
||||||
DEFAULT_SERVER = '127.0.0.1'
|
DEFAULT_SERVER = '127.0.0.1'
|
||||||
|
|||||||
@@ -135,7 +135,7 @@
|
|||||||
<form class="loginform" method="post" action="/login" onsubmit="return false;">
|
<form class="loginform" method="post" action="/login" onsubmit="return false;">
|
||||||
<div class="rlogo">{{data['title']}}</div>
|
<div class="rlogo">{{data['title']}}</div>
|
||||||
<div class="line">
|
<div class="line">
|
||||||
<input class="inputtxt" value="" name="username" datatype="*" nullmsg="请填写账户" errormsg="请填写账户" placeholder="账户" type="text">
|
<input class="inputtxt" value="" name="username" datatype="*" nullmsg="请填写账户" errormsg="请填写账户" placeholder="账户" type="text" autocomplete="on">
|
||||||
<div class="Validform_checktip"></div>
|
<div class="Validform_checktip"></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="line"><input class="inputtxt" name="password" value="" datatype="*" nullmsg="请填写密码" errormsg="请填写密码" placeholder="密码" type="password">
|
<div class="line"><input class="inputtxt" name="password" value="" datatype="*" nullmsg="请填写密码" errormsg="请填写密码" placeholder="密码" type="password">
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
<div class="line yzm" style="top: -5px;{% if not session['code'] %}display:none;{% endif %}">
|
<div class="line yzm" style="top: -5px;{% if not session['code'] %}display:none;{% endif %}">
|
||||||
<input type="text" class="inputtxt" name="code" nullmsg="请填写4位验证码" errormsg="验证码" datatype="*" placeholder="验证码">
|
<input type="text" class="inputtxt" name="code" nullmsg="请填写4位验证码" errormsg="验证码" datatype="*" placeholder="验证码">
|
||||||
<div class="Validform_checktip"></div>
|
<div class="Validform_checktip"></div>
|
||||||
<div id='mw_yzm'>{% if session['code'] %}<img width="100" height="40" class="passcode" onClick="this.src=this.src.split('?')[0] + '?'+new Date().getTime()" src="/code" style="border: 1px solid #ccc; float: right;" title="" >{% endif %}</div>
|
<div id='mw_yzm'>{% if session['code'] %}<img width="100" height="40" class="passcode" onclick="this.src=this.src.split('?')[0] + '?'+new Date().getTime()" src="/code" style="border: 1px solid #ccc; float: right;" title="" >{% endif %}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="login_btn"><input id="login-button" value="登录" type="submit"></div>
|
<div class="login_btn"><input id="login-button" value="登录" type="submit"></div>
|
||||||
<p class="pwinfo" style="display:none"></p>
|
<p class="pwinfo" style="display:none"></p>
|
||||||
@@ -205,9 +205,9 @@ $('#login-button').click(function(){
|
|||||||
var data = 'username='+username+'&password='+password+'&code='+code;
|
var data = 'username='+username+'&password='+password+'&code='+code;
|
||||||
var loadT = layer.msg("正在登录中...",{icon:16,time:0,shade: [0.3, '#000']});
|
var loadT = layer.msg("正在登录中...",{icon:16,time:0,shade: [0.3, '#000']});
|
||||||
$.post('/do_login',data,function(rdata){
|
$.post('/do_login',data,function(rdata){
|
||||||
console.log(rdata);
|
console.log('do_login',rdata);
|
||||||
layer.close(loadT);
|
layer.close(loadT);
|
||||||
if(status < 0){
|
if(!rdata.status || rdata.status < 0){
|
||||||
if(username == 'admin' && rdata.msg.indexOf('用户名') != -1){
|
if(username == 'admin' && rdata.msg.indexOf('用户名') != -1){
|
||||||
rdata.msg += ', <br>获取默认用户和密码命令: mw default';
|
rdata.msg += ', <br>获取默认用户和密码命令: mw default';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
IS_WIN = (os.name == 'nt')
|
||||||
@@ -104,6 +104,46 @@ class MwPlugin(object):
|
|||||||
mw.writeFile(self.__index, '[]')
|
mw.writeFile(self.__index, '[]')
|
||||||
self.__index_data = json.loads(mw.readFile(self.__index))
|
self.__index_data = json.loads(mw.readFile(self.__index))
|
||||||
|
|
||||||
|
def getIndexList(self):
|
||||||
|
if not os.path.exists(self.__index):
|
||||||
|
mw.writeFile(self.__index, '[]')
|
||||||
|
|
||||||
|
indexList = json.loads(mw.readFile(self.__index))
|
||||||
|
plist = []
|
||||||
|
for i in indexList:
|
||||||
|
tmp = i.split('-')
|
||||||
|
tmp_len = len(tmp)
|
||||||
|
plugin_name = tmp[0]
|
||||||
|
plugin_ver = tmp[1]
|
||||||
|
if tmp_len > 2:
|
||||||
|
tmpArr = tmp[0:tmp_len - 1]
|
||||||
|
plugin_name = '-'.join(tmpArr)
|
||||||
|
plugin_ver = tmp[tmp_len - 1]
|
||||||
|
|
||||||
|
read_json_file = self.__plugin_dir + '/' + plugin_name + '/info.json'
|
||||||
|
if os.path.exists(read_json_file):
|
||||||
|
content = mw.readFile(read_json_file)
|
||||||
|
try:
|
||||||
|
data = json.loads(content)
|
||||||
|
data = self.makeCoexistList(data)
|
||||||
|
for index in range(len(data)):
|
||||||
|
if data[index]['coexist']:
|
||||||
|
if data[index]['versions'] == plugin_ver or plugin_ver in data[index]['versions']:
|
||||||
|
data[index]['display'] = True
|
||||||
|
plist.append(data[index])
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
data[index]['display'] = True
|
||||||
|
plist.append(data[index])
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print('getIndexList:', mw.getTracebackInfo())
|
||||||
|
|
||||||
|
# 使用gevent模式时,无法使用多进程
|
||||||
|
# plist = self.checkStatusMProcess(plist)
|
||||||
|
plist = self.checkStatusMThreads(plist)
|
||||||
|
return plist
|
||||||
|
|
||||||
# 插件搜索匹配
|
# 插件搜索匹配
|
||||||
def searchKey(self, info,
|
def searchKey(self, info,
|
||||||
keyword: str | None = None,
|
keyword: str | None = None,
|
||||||
|
|||||||
@@ -0,0 +1,292 @@
|
|||||||
|
# coding:utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
import math
|
||||||
|
import psutil
|
||||||
|
|
||||||
|
|
||||||
|
import core.mw as mw
|
||||||
|
|
||||||
|
def getDiskInfo():
|
||||||
|
# 取磁盘分区信息
|
||||||
|
temp = mw.execShell("df -h -P|grep '/'|grep -v tmpfs | grep -v devfs")[0]
|
||||||
|
tempInodes = mw.execShell("df -i -P|grep '/'|grep -v tmpfs | grep -v devfs")[0]
|
||||||
|
temp1 = temp.split('\n')
|
||||||
|
tempInodes1 = tempInodes.split('\n')
|
||||||
|
diskInfo = []
|
||||||
|
n = 0
|
||||||
|
cuts = ['/mnt/cdrom', '/boot', '/boot/efi', '/dev',
|
||||||
|
'/dev/shm', '/zroot', '/run/lock', '/run', '/run/shm', '/run/user']
|
||||||
|
for tmp in temp1:
|
||||||
|
n += 1
|
||||||
|
inodes = tempInodes1[n - 1].split()
|
||||||
|
disk = tmp.split()
|
||||||
|
if len(disk) < 5:
|
||||||
|
continue
|
||||||
|
if disk[1].find('M') != -1:
|
||||||
|
continue
|
||||||
|
if disk[1].find('K') != -1:
|
||||||
|
continue
|
||||||
|
if len(disk[5].split('/')) > 4:
|
||||||
|
continue
|
||||||
|
if disk[5] in cuts:
|
||||||
|
continue
|
||||||
|
arr = {}
|
||||||
|
arr['path'] = disk[5]
|
||||||
|
tmp1 = [disk[1], disk[2], disk[3], disk[4]]
|
||||||
|
arr['size'] = tmp1
|
||||||
|
arr['inodes'] = [inodes[1], inodes[2], inodes[3], inodes[4]]
|
||||||
|
diskInfo.append(arr)
|
||||||
|
return diskInfo
|
||||||
|
|
||||||
|
class stats:
|
||||||
|
cache = {}
|
||||||
|
|
||||||
|
# 磁盘统计
|
||||||
|
def disk(self):
|
||||||
|
iokey = 'disk_stat'
|
||||||
|
diskInfo = {}
|
||||||
|
diskInfo['ALL'] = {}
|
||||||
|
diskInfo['ALL']['read_count'] = 0
|
||||||
|
diskInfo['ALL']['write_count'] = 0
|
||||||
|
diskInfo['ALL']['read_bytes'] = 0
|
||||||
|
diskInfo['ALL']['write_bytes'] = 0
|
||||||
|
diskInfo['ALL']['read_time'] = 0
|
||||||
|
diskInfo['ALL']['write_time'] = 0
|
||||||
|
diskInfo['ALL']['read_merged_count'] = 0
|
||||||
|
diskInfo['ALL']['write_merged_count'] = 0
|
||||||
|
|
||||||
|
try:
|
||||||
|
diskio = None
|
||||||
|
if iokey in self.cache:
|
||||||
|
diskio = self.cache[iokey]
|
||||||
|
|
||||||
|
mtime = int(time.time())
|
||||||
|
if not diskio:
|
||||||
|
diskio = {}
|
||||||
|
diskio['info'] = None
|
||||||
|
diskio['time'] = mtime
|
||||||
|
|
||||||
|
diskio_cache = diskio['info']
|
||||||
|
stime = mtime - diskio['time']
|
||||||
|
if not stime: stime = 1
|
||||||
|
|
||||||
|
diskio_group = psutil.disk_io_counters(perdisk=True)
|
||||||
|
if not diskio_cache:
|
||||||
|
diskio_cache = diskio_group
|
||||||
|
|
||||||
|
for disk_name in diskio_group.keys():
|
||||||
|
diskInfo[disk_name] = {}
|
||||||
|
# print('disk_name',disk_name)
|
||||||
|
# print(diskio_group[disk_name].write_time , diskio_cache[disk_name].write_time)
|
||||||
|
# print(diskio_group[disk_name].write_count , diskio_cache[disk_name].write_count)
|
||||||
|
|
||||||
|
diskInfo[disk_name]['read_count'] = int((diskio_group[disk_name].read_count - diskio_cache[disk_name].read_count) / stime)
|
||||||
|
diskInfo[disk_name]['write_count'] = int((diskio_group[disk_name].write_count - diskio_cache[disk_name].write_count) / stime)
|
||||||
|
diskInfo[disk_name]['read_bytes'] = int((diskio_group[disk_name].read_bytes - diskio_cache[disk_name].read_bytes) / stime)
|
||||||
|
diskInfo[disk_name]['write_bytes'] = int((diskio_group[disk_name].write_bytes - diskio_cache[disk_name].write_bytes) / stime)
|
||||||
|
diskInfo[disk_name]['read_time'] = int((diskio_group[disk_name].read_time - diskio_cache[disk_name].read_time) / stime)
|
||||||
|
diskInfo[disk_name]['write_time'] = int((diskio_group[disk_name].write_time - diskio_cache[disk_name].write_time) / stime)
|
||||||
|
|
||||||
|
if 'read_merged_count' in diskio_group[disk_name] and 'read_merged_count' in diskio_cache[disk_name]:
|
||||||
|
diskInfo[disk_name]['read_merged_count'] = int((diskio_group[disk_name].read_merged_count - diskio_cache[disk_name].read_merged_count) / stime)
|
||||||
|
if 'write_merged_count' in diskio_group[disk_name] and 'write_merged_count' in diskio_cache[disk_name]:
|
||||||
|
diskInfo[disk_name]['write_merged_count'] = int((diskio_group[disk_name].write_merged_count - diskio_cache[disk_name].write_merged_count) / stime)
|
||||||
|
|
||||||
|
diskInfo['ALL']['read_count'] += diskInfo[disk_name]['read_count']
|
||||||
|
diskInfo['ALL']['write_count'] += diskInfo[disk_name]['write_count']
|
||||||
|
diskInfo['ALL']['read_bytes'] += diskInfo[disk_name]['read_bytes']
|
||||||
|
diskInfo['ALL']['write_bytes'] += diskInfo[disk_name]['write_bytes']
|
||||||
|
if diskInfo['ALL']['read_time'] < diskInfo[disk_name]['read_time']:
|
||||||
|
diskInfo['ALL']['read_time'] = diskInfo[disk_name]['read_time']
|
||||||
|
if diskInfo['ALL']['write_time'] < diskInfo[disk_name]['write_time']:
|
||||||
|
diskInfo['ALL']['write_time'] = diskInfo[disk_name]['write_time']
|
||||||
|
|
||||||
|
if 'read_merged_count' in diskInfo[disk_name] and 'read_merged_count' in diskInfo[disk_name]:
|
||||||
|
diskInfo['ALL']['read_merged_count'] += diskInfo[disk_name]['read_merged_count']
|
||||||
|
if 'write_merged_count' in diskInfo[disk_name] and 'write_merged_count' in diskInfo[disk_name]:
|
||||||
|
diskInfo['ALL']['write_merged_count'] += diskInfo[disk_name]['write_merged_count']
|
||||||
|
|
||||||
|
self.cache[iokey] = {'info':diskio_group,'time':mtime}
|
||||||
|
except Exception as e:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return diskInfo
|
||||||
|
|
||||||
|
# 网络统计
|
||||||
|
def network(self):
|
||||||
|
netInfo = {}
|
||||||
|
|
||||||
|
netInfo['ALL'] = {}
|
||||||
|
netInfo['ALL']['up'] = 0
|
||||||
|
netInfo['ALL']['down'] = 0
|
||||||
|
netInfo['ALL']['upTotal'] = 0
|
||||||
|
netInfo['ALL']['downTotal'] = 0
|
||||||
|
netInfo['ALL']['upPackets'] = 0
|
||||||
|
netInfo['ALL']['downPackets'] = 0
|
||||||
|
|
||||||
|
mtime = time.time()
|
||||||
|
iokey = 'net_stat'
|
||||||
|
netio = None
|
||||||
|
if iokey in self.cache:
|
||||||
|
netio = self.cache[iokey]
|
||||||
|
|
||||||
|
if not netio:
|
||||||
|
netio = {}
|
||||||
|
netio['info'] = None
|
||||||
|
netio['all_io'] = None
|
||||||
|
netio['time'] = mtime
|
||||||
|
|
||||||
|
stime = mtime - netio['time']
|
||||||
|
if not stime: stime = 1
|
||||||
|
|
||||||
|
# print("new:",stime)
|
||||||
|
netio_group = psutil.net_io_counters(pernic=True).keys()
|
||||||
|
|
||||||
|
netio_cache = netio['info']
|
||||||
|
allio_cache = netio['all_io']
|
||||||
|
if not netio_cache:
|
||||||
|
netio_cache = {}
|
||||||
|
|
||||||
|
netio_group_t = {}
|
||||||
|
for name in netio_group:
|
||||||
|
netInfo[name] = {}
|
||||||
|
|
||||||
|
io_data = psutil.net_io_counters(pernic=True).get(name)
|
||||||
|
if not name in netio_cache:
|
||||||
|
netio_cache[name] = io_data
|
||||||
|
|
||||||
|
netio_group_t[name] = io_data
|
||||||
|
|
||||||
|
netInfo[name]['up'] = round(float((io_data[0] - netio_cache[name][0]) / stime), 2)
|
||||||
|
netInfo[name]['down'] = round(float((io_data[1] - netio_cache[name][1])/ stime), 2)
|
||||||
|
|
||||||
|
netInfo[name]['upTotal'] = io_data[0]
|
||||||
|
netInfo[name]['downTotal'] = io_data[1]
|
||||||
|
netInfo[name]['upPackets'] = io_data[2]
|
||||||
|
netInfo[name]['downPackets'] = io_data[3]
|
||||||
|
|
||||||
|
all_io = psutil.net_io_counters()[:4]
|
||||||
|
if not allio_cache:
|
||||||
|
allio_cache = all_io
|
||||||
|
|
||||||
|
netInfo['ALL']['up'] = round(float((all_io[0] - allio_cache[0]) /stime), 2)
|
||||||
|
netInfo['ALL']['down'] = round(float((all_io[1] - allio_cache[1]) /stime), 2)
|
||||||
|
netInfo['ALL']['upTotal'] = all_io[0]
|
||||||
|
netInfo['ALL']['downTotal'] = all_io[1]
|
||||||
|
netInfo['ALL']['upPackets'] = all_io[2]
|
||||||
|
netInfo['ALL']['downPackets'] = all_io[3]
|
||||||
|
|
||||||
|
self.cache[iokey] = {'info':netio_group_t,'all_io':all_io,'time':mtime}
|
||||||
|
return netInfo
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def getLoadAverage():
|
||||||
|
c = os.getloadavg()
|
||||||
|
data = {}
|
||||||
|
data['one'] = round(float(c[0]), 2)
|
||||||
|
data['five'] = round(float(c[1]), 2)
|
||||||
|
data['fifteen'] = round(float(c[2]), 2)
|
||||||
|
data['max'] = psutil.cpu_count() * 2
|
||||||
|
data['limit'] = data['max']
|
||||||
|
data['safe'] = data['max'] * 0.75
|
||||||
|
return data
|
||||||
|
|
||||||
|
def getSystemVersion():
|
||||||
|
# 取操作系统版本
|
||||||
|
current_os = mw.getOs()
|
||||||
|
# sys_temper = self.getSystemDeviceTemperature()
|
||||||
|
# print(sys_temper)
|
||||||
|
# mac
|
||||||
|
if current_os == 'darwin':
|
||||||
|
data = mw.execShell('sw_vers')[0]
|
||||||
|
data_list = data.strip().split("\n")
|
||||||
|
mac_version = ''
|
||||||
|
for x in data_list:
|
||||||
|
xlist = x.split("\t")
|
||||||
|
mac_version += xlist[len(xlist)-1] + ' '
|
||||||
|
|
||||||
|
arch_ver = mw.execShell("arch")
|
||||||
|
return mac_version + " (" + arch_ver[0].strip() + ")"
|
||||||
|
|
||||||
|
# freebsd
|
||||||
|
if current_os.startswith('freebsd'):
|
||||||
|
version = mw.execShell(
|
||||||
|
"cat /etc/*-release | grep PRETTY_NAME | awk -F = '{print $2}' | awk -F '\"' '{print $2}'")
|
||||||
|
arch_ver = mw.execShell(
|
||||||
|
"sysctl -a | egrep -i 'hw.machine_arch' | awk -F ':' '{print $2}'")
|
||||||
|
return version[0].strip() + " (" + arch_ver[0].strip() + ")"
|
||||||
|
|
||||||
|
redhat_series = '/etc/redhat-release'
|
||||||
|
if os.path.exists(redhat_series):
|
||||||
|
version = mw.readFile('/etc/redhat-release')
|
||||||
|
version = version.replace('release ', '').strip()
|
||||||
|
|
||||||
|
arch_ver = mw.execShell("arch")
|
||||||
|
return version + " (" + arch_ver[0].strip() + ")"
|
||||||
|
|
||||||
|
os_series = '/etc/os-release'
|
||||||
|
if os.path.exists(os_series):
|
||||||
|
version = mw.execShell(
|
||||||
|
"cat /etc/*-release | grep PRETTY_NAME | awk -F = '{print $2}' | awk -F '\"' '{print $2}'")
|
||||||
|
|
||||||
|
arch_ver = mw.execShell("arch")
|
||||||
|
return version[0].strip() + " (" + arch_ver[0].strip() + ")"
|
||||||
|
|
||||||
|
def getBootTime():
|
||||||
|
# 取系统启动时间
|
||||||
|
uptime = mw.readFile('/proc/uptime')
|
||||||
|
if uptime == False:
|
||||||
|
start_time = psutil.boot_time()
|
||||||
|
run_time = time.time() - start_time
|
||||||
|
else:
|
||||||
|
run_time = uptime.split()[0]
|
||||||
|
tStr = float(run_time)
|
||||||
|
min = tStr / 60
|
||||||
|
hours = min / 60
|
||||||
|
days = math.floor(hours / 24)
|
||||||
|
hours = math.floor(hours - (days * 24))
|
||||||
|
min = math.floor(min - (days * 60 * 24) - (hours * 60))
|
||||||
|
return mw.getInfo('已不间断运行: {1}天{2}小时{3}分钟', (str(int(days)), str(int(hours)), str(int(min))))
|
||||||
|
|
||||||
|
def getCpuInfo(interval=1):
|
||||||
|
# 取CPU信息
|
||||||
|
cpuCount = psutil.cpu_count()
|
||||||
|
cpuLogicalNum = psutil.cpu_count(logical=False)
|
||||||
|
used = psutil.cpu_percent(interval=interval)
|
||||||
|
cpuLogicalNum = 0
|
||||||
|
if os.path.exists('/proc/cpuinfo'):
|
||||||
|
c_tmp = mw.readFile('/proc/cpuinfo')
|
||||||
|
d_tmp = re.findall("physical id.+", c_tmp)
|
||||||
|
cpuLogicalNum = len(set(d_tmp))
|
||||||
|
|
||||||
|
used_all = psutil.cpu_percent(percpu=True)
|
||||||
|
cpu_name = mw.getCpuType() + " * {}".format(cpuLogicalNum)
|
||||||
|
return used, cpuCount, used_all, cpu_name, cpuCount, cpuLogicalNum
|
||||||
|
|
||||||
|
def getMemInfo():
|
||||||
|
# 取内存信息
|
||||||
|
mem = psutil.virtual_memory()
|
||||||
|
if sys.platform == 'darwin':
|
||||||
|
memInfo = {'memTotal': mem.total}
|
||||||
|
memInfo['memRealUsed'] = memInfo['memTotal'] * (mem.percent / 100)
|
||||||
|
else:
|
||||||
|
memInfo = {
|
||||||
|
'memTotal': mem.total,
|
||||||
|
'memFree': mem.free,
|
||||||
|
'memBuffers': mem.buffers,
|
||||||
|
'memCached': mem.cached
|
||||||
|
}
|
||||||
|
memInfo['memRealUsed'] = memInfo['memTotal'] - memInfo['memFree'] - memInfo['memBuffers'] - memInfo['memCached']
|
||||||
|
return memInfo
|
||||||
Executable
+143
@@ -0,0 +1,143 @@
|
|||||||
|
# coding: utf-8
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# MW-Linux面板
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved.
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# Author: midoks <midoks@163.com>
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
# 验证码操作
|
||||||
|
# ---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
import random
|
||||||
|
import math
|
||||||
|
|
||||||
|
from PIL import Image, ImageDraw, ImageFont, ImageFilter
|
||||||
|
|
||||||
|
class vieCode:
|
||||||
|
__fontSize = 20 # 字体大小
|
||||||
|
__width = 120 # 画布宽度
|
||||||
|
__heigth = 45 # 画布高度
|
||||||
|
__length = 4 # 验证码长度
|
||||||
|
__draw = None # 画布
|
||||||
|
__img = None # 图片资源
|
||||||
|
__code = None # 验证码字符
|
||||||
|
__str = None # 自定义验证码字符集
|
||||||
|
__inCurve = True # 是否画干扰线
|
||||||
|
__inNoise = True # 是否画干扰点
|
||||||
|
__type = 2 # 验证码类型 1、纯字母 2、数字字母混合
|
||||||
|
__fontPatn = 'class/fonts/2.ttf' # 字体
|
||||||
|
|
||||||
|
def GetCodeImage(self, size=80, length=4):
|
||||||
|
'''获取验证码图片
|
||||||
|
@param int size 验证码大小
|
||||||
|
@param int length 验证码长度
|
||||||
|
'''
|
||||||
|
# 准备基础数据
|
||||||
|
self.__length = length
|
||||||
|
self.__fontSize = size
|
||||||
|
self.__width = self.__fontSize * self.__length
|
||||||
|
self.__heigth = int(self.__fontSize * 1.5)
|
||||||
|
|
||||||
|
# 生成验证码图片
|
||||||
|
self.__createCode()
|
||||||
|
self.__createImage()
|
||||||
|
self.__createNoise()
|
||||||
|
self.__printString()
|
||||||
|
self.__cerateFilter()
|
||||||
|
|
||||||
|
return self.__img, self.__code
|
||||||
|
|
||||||
|
def __cerateFilter(self):
|
||||||
|
'''模糊处理'''
|
||||||
|
self.__img = self.__img.filter(ImageFilter.BLUR)
|
||||||
|
filter = ImageFilter.ModeFilter(8)
|
||||||
|
self.__img = self.__img.filter(filter)
|
||||||
|
|
||||||
|
def __createCode(self):
|
||||||
|
'''创建验证码字符'''
|
||||||
|
# 是否自定义字符集合
|
||||||
|
if not self.__str:
|
||||||
|
# 源文本
|
||||||
|
number = "3456789"
|
||||||
|
srcLetter = "qwertyuipasdfghjkzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM"
|
||||||
|
srcUpper = srcLetter.upper()
|
||||||
|
if self.__type == 1:
|
||||||
|
self.__str = number
|
||||||
|
else:
|
||||||
|
self.__str = srcLetter + srcUpper + number
|
||||||
|
|
||||||
|
# 构造验证码
|
||||||
|
self.__code = random.sample(self.__str, self.__length)
|
||||||
|
|
||||||
|
def __createImage(self):
|
||||||
|
'''创建画布'''
|
||||||
|
bgColor = (random.randint(200, 255), random.randint(
|
||||||
|
200, 255), random.randint(200, 255))
|
||||||
|
self.__img = Image.new('RGB', (self.__width, self.__heigth), bgColor)
|
||||||
|
self.__draw = ImageDraw.Draw(self.__img)
|
||||||
|
|
||||||
|
def __createNoise(self):
|
||||||
|
'''画干扰点'''
|
||||||
|
if not self.__inNoise:
|
||||||
|
return
|
||||||
|
font = ImageFont.truetype(self.__fontPatn, int(self.__fontSize / 1.5))
|
||||||
|
for i in range(5):
|
||||||
|
# 杂点颜色
|
||||||
|
noiseColor = (random.randint(150, 200), random.randint(
|
||||||
|
150, 200), random.randint(150, 200))
|
||||||
|
putStr = random.sample(self.__str, 2)
|
||||||
|
for j in range(2):
|
||||||
|
# 绘杂点
|
||||||
|
size = (random.randint(-10, self.__width),
|
||||||
|
random.randint(-10, self.__heigth))
|
||||||
|
self.__draw.text(size, putStr[j], font=font, fill=noiseColor)
|
||||||
|
pass
|
||||||
|
|
||||||
|
def __createCurve(self):
|
||||||
|
'''画干扰线'''
|
||||||
|
if not self.__inCurve:
|
||||||
|
return
|
||||||
|
x = y = 0
|
||||||
|
|
||||||
|
# 计算曲线系数
|
||||||
|
a = random.uniform(1, self.__heigth / 2)
|
||||||
|
b = random.uniform(-self.__width / 4, self.__heigth / 4)
|
||||||
|
f = random.uniform(-self.__heigth / 4, self.__heigth / 4)
|
||||||
|
t = random.uniform(self.__heigth, self.__width * 2)
|
||||||
|
xend = random.randint(self.__width / 2, self.__width * 2)
|
||||||
|
w = (2 * math.pi) / t
|
||||||
|
|
||||||
|
# 画曲线
|
||||||
|
color = (random.randint(30, 150), random.randint(
|
||||||
|
30, 150), random.randint(30, 150))
|
||||||
|
for x in range(xend):
|
||||||
|
if w != 0:
|
||||||
|
for k in range(int(self.__heigth / 10)):
|
||||||
|
y = a * math.sin(w * x + f) + b + self.__heigth / 2
|
||||||
|
i = int(self.__fontSize / 5)
|
||||||
|
while i > 0:
|
||||||
|
px = x + i
|
||||||
|
py = y + i + k
|
||||||
|
self.__draw.point((px, py), color)
|
||||||
|
i -= i
|
||||||
|
|
||||||
|
def __printString(self):
|
||||||
|
'''打印验证码字符串'''
|
||||||
|
font = ImageFont.truetype(self.__fontPatn, self.__fontSize)
|
||||||
|
x = 0
|
||||||
|
# 打印字符到画板
|
||||||
|
for i in range(self.__length):
|
||||||
|
# 设置字体随机颜色
|
||||||
|
color = (random.randint(30, 150), random.randint(
|
||||||
|
30, 150), random.randint(30, 150))
|
||||||
|
# 计算座标
|
||||||
|
x = random.uniform(self.__fontSize * i * 0.95,
|
||||||
|
self.__fontSize * i * 1.1)
|
||||||
|
y = self.__fontSize * random.uniform(0.3, 0.5)
|
||||||
|
# 打印字符
|
||||||
|
self.__draw.text((x, y), self.__code[i], font=font, fill=color)
|
||||||
Reference in New Issue
Block a user