mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-09 23:39:25 +08:00
update
This commit is contained in:
@@ -185,3 +185,4 @@ plugins/goedge-node
|
||||
plugins/goedge-happy
|
||||
plugins/dztasks
|
||||
|
||||
data/default_new.pl
|
||||
|
||||
@@ -42,7 +42,7 @@ class config_api:
|
||||
'bind_domain' : 'data/bind_domain.pl', # 面板域名绑定
|
||||
'unauth_status' : 'data/unauthorized_status.pl', # URL路径未成功显示状态
|
||||
'auth_secret': 'data/auth_secret.pl', # 二次验证密钥
|
||||
'ssl':'ssl/choose.pl', # ssl设置
|
||||
'ssl':'ssl/choose.pl', # ssl设置
|
||||
'hook_database' : 'data/hook_database.json', # 数据库钩子
|
||||
'hook_menu' : 'data/hook_menu.json', # 菜单钩子
|
||||
'hook_global_static' : 'data/hook_global_static.json', # 静态文件钩子
|
||||
|
||||
@@ -717,7 +717,6 @@ class system_api:
|
||||
|
||||
self.cache[iokey] = {'info':diskio_group,'time':mtime}
|
||||
except Exception as e:
|
||||
# print(mw.getTracebackInfo())
|
||||
pass
|
||||
|
||||
return diskInfo
|
||||
|
||||
@@ -220,7 +220,7 @@ def getDbConfValue():
|
||||
rep_scope = r"\[database\](.*?)\["
|
||||
tmp = re.findall(rep_scope, content, re.S)
|
||||
|
||||
rep = '(\w*)\s*=\s*(.*)'
|
||||
rep = '(\\w*)\\s*=\\s*(.*)'
|
||||
tmp = re.findall(rep, tmp[0])
|
||||
r = {}
|
||||
for x in range(len(tmp)):
|
||||
|
||||
+35
-4
@@ -8,7 +8,11 @@
|
||||
# Author: midoks <midoks@163.com>
|
||||
# ---------------------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
import uuid
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from flask import Flask
|
||||
from flask_socketio import SocketIO, emit, send
|
||||
@@ -20,6 +24,7 @@ from flask_migrate import Migrate
|
||||
from werkzeug.local import LocalProxy
|
||||
|
||||
from admin.model import db as sys_db
|
||||
from admin import setup
|
||||
|
||||
import core.mw as mw
|
||||
import setting
|
||||
@@ -33,25 +38,46 @@ socketio = SocketIO(manage_session=False, async_mode='threading',
|
||||
|
||||
app = Flask(__name__, template_folder='templates/default')
|
||||
|
||||
# app.debug = True
|
||||
|
||||
# 静态文件配置
|
||||
from whitenoise import WhiteNoise
|
||||
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的配置
|
||||
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
|
||||
|
||||
|
||||
# 初始化db
|
||||
sys_db.init_app(app)
|
||||
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():
|
||||
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:
|
||||
app.register_blueprint(module)
|
||||
|
||||
@app.before_request
|
||||
def requestCheck():
|
||||
print("hh")
|
||||
|
||||
@app.after_request
|
||||
def requestAfter(response):
|
||||
@@ -127,6 +156,8 @@ def inject_global_variables():
|
||||
# return jsonify(result)
|
||||
|
||||
|
||||
|
||||
|
||||
# Log the startup
|
||||
app.logger.info('########################################################')
|
||||
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 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('/')
|
||||
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'])
|
||||
def check_login():
|
||||
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
|
||||
|
||||
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')
|
||||
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(
|
||||
engine_options={
|
||||
'pool_size': setting.CONFIG_DATABASE_CONNECTION_POOL_SIZE,
|
||||
'max_overflow': setting.CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW
|
||||
}
|
||||
)
|
||||
engine_options={
|
||||
'pool_size': setting.CONFIG_DATABASE_CONNECTION_POOL_SIZE,
|
||||
'max_overflow': setting.CONFIG_DATABASE_CONNECTION_MAX_OVERFLOW
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class Version(db.Model):
|
||||
@@ -42,11 +42,12 @@ class Option(db.Model):
|
||||
__tablename__ = 'option'
|
||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||
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="内容")
|
||||
|
||||
class User(db.Model):
|
||||
class Users(db.Model):
|
||||
"""定义登录用户"""
|
||||
__tablename__ = 'user'
|
||||
__tablename__ = 'users'
|
||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||
name = db.Column(db.String(128), unique=True, 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="登录时间")
|
||||
phone = db.Column(db.String(20), unique=False, 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):
|
||||
"""定义计划任务"""
|
||||
@@ -73,7 +76,7 @@ class Crontab(db.Model):
|
||||
save = db.Column(db.Integer, unique=False, nullable=True, default=3,comment="备份数量")
|
||||
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="添加时间")
|
||||
update_time = db.Column(db.TEXT, nullable=False, comment="更新时间")
|
||||
|
||||
class Logs(db.Model):
|
||||
"""定义日志"""
|
||||
@@ -88,8 +91,8 @@ class Firewall(db.Model):
|
||||
"""定义防火墙"""
|
||||
__tablename__ = 'firewall'
|
||||
id = db.Column(db.Integer(), primary_key=True,autoincrement=True, comment="ID")
|
||||
port = db.Column(db.Integer(), unique=True, nullable=False, comment="端口")
|
||||
protocol = db.Column(db.Integer(), unique=True, nullable=False, comment="协议/tcp/udp")
|
||||
port = db.Column(db.Integer(), unique=False, nullable=False, comment="端口")
|
||||
protocol = db.Column(db.Integer(), unique=False, nullable=False, comment="协议/tcp/udp")
|
||||
ps = 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="更新时间")
|
||||
@@ -106,6 +109,84 @@ class Backup(db.Model):
|
||||
size = db.Column(db.Integer(), unique=False, 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'])
|
||||
@panel_login_required
|
||||
def init():
|
||||
plugin_names = {
|
||||
'openresty': '1.25.3',
|
||||
@@ -38,6 +39,13 @@ def init():
|
||||
}
|
||||
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'])
|
||||
@panel_login_required
|
||||
@@ -102,7 +110,6 @@ def run():
|
||||
|
||||
pg = MwPlugin.instance()
|
||||
data = pg.run(name, func, version, args, script)
|
||||
|
||||
if data[1] == '':
|
||||
r = mw.returnData(True, "OK", data[0].strip())
|
||||
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 .firewall import blueprint as FirewallModule
|
||||
from .control import blueprint as ControlModule
|
||||
from .system import blueprint as SystemModule
|
||||
|
||||
def get_submodules():
|
||||
return [
|
||||
@@ -33,5 +34,6 @@ def get_submodules():
|
||||
CrontabModule,
|
||||
FirewallModule,
|
||||
ControlModule,
|
||||
SystemModule,
|
||||
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
|
||||
|
||||
def panel_login_required(func):
|
||||
|
||||
print('panel_login_required',func)
|
||||
|
||||
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
print('panel_login_required', args, kwargs)
|
||||
return func(*args, **kwargs)
|
||||
return wrapper
|
||||
@@ -14,5 +14,8 @@
|
||||
APP_NAME = 'mdserver-web'
|
||||
APP_ICON = 'icon'
|
||||
|
||||
APP_LOG_NAME = 'panel'
|
||||
APP_SQLITE_NAME = 'panel'
|
||||
|
||||
# Copyright string for display in the app
|
||||
APP_COPYRIGHT = 'Copyright (C) 2018-∞ All rights reserved.'
|
||||
+83
-2
@@ -116,11 +116,11 @@ def getUniqueId():
|
||||
return unique_id
|
||||
|
||||
def returnData(status, msg, data=None):
|
||||
if data == None:
|
||||
return {'status': status, 'msg': msg}
|
||||
return {'status': status, 'msg': msg, 'data': data}
|
||||
|
||||
def returnJson(status, msg, data=None):
|
||||
if data == None:
|
||||
return getJson({'status': status, 'msg': msg})
|
||||
return getJson({'status': status, 'msg': msg, 'data': data})
|
||||
|
||||
def readFile(filename):
|
||||
@@ -163,6 +163,52 @@ def systemdCfgDir():
|
||||
# local test
|
||||
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):
|
||||
import json
|
||||
return json.dumps(data)
|
||||
@@ -240,6 +286,41 @@ def getSqitePrefix():
|
||||
prefix = 'sqlite:////'
|
||||
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):
|
||||
pyVersion = sys.version_info[0]
|
||||
try:
|
||||
|
||||
+28
-1
@@ -18,7 +18,9 @@ import logging
|
||||
import os
|
||||
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
|
||||
|
||||
DEBUG = False
|
||||
@@ -28,6 +30,31 @@ CONFIG_DATABASE_CONNECTION_POOL_SIZE = 5
|
||||
# 允许溢出超过连接池大小的连接数
|
||||
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'
|
||||
|
||||
@@ -135,7 +135,7 @@
|
||||
<form class="loginform" method="post" action="/login" onsubmit="return false;">
|
||||
<div class="rlogo">{{data['title']}}</div>
|
||||
<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>
|
||||
<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 %}">
|
||||
<input type="text" class="inputtxt" name="code" nullmsg="请填写4位验证码" errormsg="验证码" datatype="*" placeholder="验证码">
|
||||
<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 class="login_btn"><input id="login-button" value="登录" type="submit"></div>
|
||||
<p class="pwinfo" style="display:none"></p>
|
||||
@@ -205,9 +205,9 @@ $('#login-button').click(function(){
|
||||
var data = 'username='+username+'&password='+password+'&code='+code;
|
||||
var loadT = layer.msg("正在登录中...",{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/do_login',data,function(rdata){
|
||||
console.log(rdata);
|
||||
console.log('do_login',rdata);
|
||||
layer.close(loadT);
|
||||
if(status < 0){
|
||||
if(!rdata.status || rdata.status < 0){
|
||||
if(username == 'admin' && rdata.msg.indexOf('用户名') != -1){
|
||||
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, '[]')
|
||||
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,
|
||||
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