diff --git a/plugins/docker/ico.png b/plugins/docker/ico.png new file mode 100644 index 000000000..db39a8cab Binary files /dev/null and b/plugins/docker/ico.png differ diff --git a/plugins/docker/index.html b/plugins/docker/index.html new file mode 100755 index 000000000..c631648fc --- /dev/null +++ b/plugins/docker/index.html @@ -0,0 +1,21 @@ +
+
+
+
+

服务

+

自启动

+

配置修改

+

性能调整

+

负载状态

+

日志

+
+
+
+
+
+
+ \ No newline at end of file diff --git a/plugins/docker/index.py b/plugins/docker/index.py new file mode 100755 index 000000000..50855ff0f --- /dev/null +++ b/plugins/docker/index.py @@ -0,0 +1,336 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import re + +sys.path.append(os.getcwd() + "/class/core") +import mw + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'docker' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getInitDFile(): + if app_debug: + return '/tmp/' + getPluginName() + return '/etc/init.d/' + getPluginName() + + +def getConf(): + path = getServerDir() + "/redis.conf" + return path + + +def getConfTpl(): + path = getPluginDir() + "/config/redis.conf" + return path + + +def getInitDTpl(): + path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl" + return path + + +def getArgs(): + args = sys.argv[3:] + tmp = {} + args_len = len(args) + + if args_len == 1: + t = args[0].strip('{').strip('}') + if t.strip() == '': + tmp = [] + else: + t = t.split(':') + tmp[t[0]] = t[1] + tmp[t[0]] = t[1] + elif args_len > 1: + for i in range(len(args)): + t = args[i].split(':') + tmp[t[0]] = t[1] + return tmp + + +def status(): + data = mw.execShell( + "ps -ef|grep redis |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'") + + if data[0] == '': + return 'stop' + return 'start' + + +def initDreplace(): + + file_tpl = getInitDTpl() + service_path = os.path.dirname(os.getcwd()) + + initD_path = getServerDir() + '/init.d' + if not os.path.exists(initD_path): + os.mkdir(initD_path) + file_bin = initD_path + '/' + getPluginName() + + # initd replace + if not os.path.exists(file_bin): + content = mw.readFile(file_tpl) + content = content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(file_bin, content) + mw.execShell('chmod +x ' + file_bin) + + # log + dataLog = getServerDir() + '/data' + if not os.path.exists(dataLog): + mw.execShell('chmod +x ' + file_bin) + + # # config replace + # dst_conf = getServerDir() + '/redis.conf' + # dst_conf_init = getServerDir() + '/init.pl' + # if not os.path.exists(dst_conf_init): + # conf_content = mw.readFile(getConfTpl()) + # conf_content = conf_content.replace('{$SERVER_PATH}', service_path) + # conf_content = conf_content.replace( + # '{$REDIS_PASS}', mw.getRandomString(10)) + + # mw.writeFile(dst_conf, conf_content) + # mw.writeFile(dst_conf_init, 'ok') + + # # systemd + # systemDir = mw.systemdCfgDir() + # systemService = systemDir + '/redis.service' + # systemServiceTpl = getPluginDir() + '/init.d/redis.service.tpl' + # if os.path.exists(systemDir) and not os.path.exists(systemService): + # service_path = mw.getServerDir() + # se_content = mw.readFile(systemServiceTpl) + # se_content = se_content.replace('{$SERVER_PATH}', service_path) + # mw.writeFile(systemService, se_content) + # mw.execShell('systemctl daemon-reload') + + return file_bin + + +def redisOp(method): + file = initDreplace() + + if not mw.isAppleSystem(): + data = mw.execShell('systemctl ' + method + ' redis') + if data[1] == '': + return 'ok' + return data[1] + + data = mw.execShell(file + ' start') + if data[1] == '': + return 'ok' + return 'fail' + + +def start(): + return redisOp('start') + + +def stop(): + return redisOp('stop') + + +def restart(): + status = redisOp('restart') + + log_file = runLog() + mw.execShell("echo '' > " + log_file) + return status + + +def reload(): + return redisOp('reload') + + +def runInfo(): + s = status() + if s == 'stop': + return mw.returnJson(False, '未启动') + + requirepass = "" + + conf = getServerDir() + '/redis.conf' + content = mw.readFile(conf) + rep = "^(requirepass" + ')\s*([.0-9A-Za-z_& ~]+)' + tmp = re.search(rep, content, re.M) + if tmp: + requirepass = tmp.groups()[1] + + default_ip = '127.0.0.1' + # findDebian = mw.execShell('cat /etc/issue |grep Debian') + # if findDebian[0] != '': + # default_ip = mw.getLocalIp() + cmd = getServerDir() + "/bin/redis-cli -h " + default_ip + " info" + if requirepass != "": + cmd = getServerDir() + '/bin/redis-cli -h ' + default_ip + \ + ' -a "' + requirepass + '" info' + + data = mw.execShell(cmd)[0] + res = [ + 'tcp_port', + 'uptime_in_days', # 已运行天数 + 'connected_clients', # 连接的客户端数量 + 'used_memory', # Redis已分配的内存总量 + 'used_memory_rss', # Redis占用的系统内存总量 + 'used_memory_peak', # Redis所用内存的高峰值 + 'mem_fragmentation_ratio', # 内存碎片比率 + 'total_connections_received', # 运行以来连接过的客户端的总数量 + 'total_commands_processed', # 运行以来执行过的命令的总数量 + 'instantaneous_ops_per_sec', # 服务器每秒钟执行的命令数量 + 'keyspace_hits', # 查找数据库键成功的次数 + 'keyspace_misses', # 查找数据库键失败的次数 + 'latest_fork_usec' # 最近一次 fork() 操作耗费的毫秒数 + ] + data = data.split("\n") + result = {} + for d in data: + if len(d) < 3: + continue + t = d.strip().split(':') + if not t[0] in res: + continue + result[t[0]] = t[1] + return mw.getJson(result) + + +def initdStatus(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + shell_cmd = 'systemctl status ' + \ + getPluginName() + ' | grep loaded | grep "enabled;"' + data = mw.execShell(shell_cmd) + if data[0] == '': + return 'fail' + return 'ok' + + +def initdInstall(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl enable ' + getPluginName()) + return 'ok' + + +def initdUinstall(): + if mw.isAppleSystem(): + return "Apple Computer does not support" + + mw.execShell('systemctl disable ' + getPluginName()) + return 'ok' + + +def runLog(): + return getServerDir() + '/data/redis.log' + + +def getRedisConfInfo(): + conf = getServerDir() + '/redis.conf' + content = mw.readFile(conf) + + gets = [ + {'name': 'bind', 'type': 2, 'ps': '绑定IP(修改绑定IP可能会存在安全隐患)'}, + {'name': 'port', 'type': 2, 'ps': '绑定端口'}, + {'name': 'timeout', 'type': 2, 'ps': '空闲链接超时时间,0表示不断开'}, + {'name': 'maxclients', 'type': 2, 'ps': '最大输入时间'}, + {'name': 'databases', 'type': 2, 'ps': '数据库数量'}, + {'name': 'requirepass', 'type': 2, 'ps': 'redis密码,留空代表没有设置密码'}, + {'name': 'maxmemory', 'type': 2, 'ps': 'MB,最大使用内存,0表示不限制'} + ] + content = mw.readFile(conf) + + result = [] + for g in gets: + rep = "^(" + g['name'] + ')\s*([.0-9A-Za-z_& ~]+)' + tmp = re.search(rep, content, re.M) + if not tmp: + g['value'] = '' + result.append(g) + continue + g['value'] = tmp.groups()[1] + if g['name'] == 'maxmemory': + g['value'] = g['value'].strip("mb") + result.append(g) + + return result + + +def getRedisConf(): + data = getRedisConfInfo() + return mw.getJson(data) + + +def submitRedisConf(): + gets = ['bind', 'port', 'timeout', 'maxclients', + 'databases', 'requirepass', 'maxmemory'] + args = getArgs() + conf = getServerDir() + '/redis.conf' + content = mw.readFile(conf) + for g in gets: + if g in args: + rep = g + '\s*([.0-9A-Za-z_& ~]+)' + val = g + ' ' + args[g] + + if g == 'maxmemory': + val = g + ' ' + args[g] + "mb" + + if g == 'requirepass' and args[g] == '': + content = re.sub('requirepass', '#requirepass', content) + if g == 'requirepass' and args[g] != '': + content = re.sub('#requirepass', 'requirepass', content) + content = re.sub(rep, val, content) + + if g != 'requirepass': + content = re.sub(rep, val, content) + mw.writeFile(conf, content) + reload() + return mw.returnJson(True, '设置成功') + +if __name__ == "__main__": + func = sys.argv[1] + if func == 'status': + print(status()) + elif func == 'start': + print(start()) + elif func == 'stop': + print(stop()) + elif func == 'restart': + print(restart()) + elif func == 'reload': + print(reload()) + elif func == 'initd_status': + print(initdStatus()) + elif func == 'initd_install': + print(initdInstall()) + elif func == 'initd_uninstall': + print(initdUinstall()) + elif func == 'run_info': + print(runInfo()) + elif func == 'conf': + print(getConf()) + elif func == 'run_log': + print(runLog()) + elif func == 'get_redis_conf': + print(getRedisConf()) + elif func == 'submit_redis_conf': + print(submitRedisConf()) + else: + print('error') diff --git a/plugins/docker/info.json b/plugins/docker/info.json new file mode 100755 index 000000000..9ba8ca0fd --- /dev/null +++ b/plugins/docker/info.json @@ -0,0 +1,18 @@ +{ + "sort": 7, + "ps": "Docker 是一个开源的应用容器引擎(开发测试中)", + "name": "docker", + "title": "Docker", + "shell": "install.sh", + "versions":["1.0"], + "updates":["1.0"], + "tip": "soft", + "checks": "server/docker", + "path": "server/docker", + "display": 1, + "author": "Zend", + "date": "2017-04-01", + "home": "https://docker.io", + "type": 0, + "pid": "2" +} \ No newline at end of file diff --git a/plugins/docker/install.sh b/plugins/docker/install.sh new file mode 100755 index 000000000..f06eb0ae2 --- /dev/null +++ b/plugins/docker/install.sh @@ -0,0 +1,63 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + + +install_tmp=${rootPath}/tmp/mw_install.pl + +VERSION=$2 + +Install_Docker() +{ + echo '正在安装脚本文件...' > $install_tmp + mkdir -p $serverPath/source + + if [ ! -f $serverPath/source/redis-${VERSION}.tar.gz ];then + wget -O $serverPath/source/redis-${VERSION}.tar.gz http://download.redis.io/releases/redis-${VERSION}.tar.gz + fi + + cd $serverPath/source && tar -zxvf redis-${VERSION}.tar.gz + + mkdir -p $serverPath/redis + mkdir -p $serverPath/redis/data + cd redis-${VERSION} && make PREFIX=$serverPath/redis install + sed '/^ *#/d' redis.conf > $serverPath/redis/redis.conf + + if [ -d $serverPath/redis ];then + echo "${VERSION}" > $serverPath/redis/version.pl + echo '安装完成' > $install_tmp + + + cd ${rootPath} && python3 ${rootPath}/plugins/redis/index.py start + cd ${rootPath} && python3 ${rootPath}/plugins/redis/index.py initd_install + fi +} + +Uninstall_Docker() +{ + if [ -f /usr/lib/systemd/system/redis.service ];then + systemctl stop redis + systemctl disable redis + rm -rf /usr/lib/systemd/system/redis.service + systemctl daemon-reload + fi + + if [ -f $serverPath/redis/initd/redis ];then + $serverPath/redis/initd/redis stop + fi + + rm -rf $serverPath/redis + echo "Uninstall_redis" > $install_tmp +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_Docker +else + Uninstall_Docker +fi diff --git a/plugins/docker/js/docker.js b/plugins/docker/js/docker.js new file mode 100755 index 000000000..22ea52707 --- /dev/null +++ b/plugins/docker/js/docker.js @@ -0,0 +1,143 @@ +function redisPost(method, version, args,callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + + var req_data = {}; + req_data['name'] = 'docker'; + req_data['func'] = method; + req_data['version'] = version; + + if (typeof(args) == 'string'){ + req_data['args'] = JSON.stringify(toArrayObject(args)); + } else { + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/run', req_data, function(data) { + layer.close(loadT); + if (!data.status){ + //错误展示10S + layer.msg(data.msg,{icon:0,time:2000,shade: [10, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function redisPostCallbak(method, version, args,callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + + var req_data = {}; + req_data['name'] = 'docker'; + req_data['func'] = method; + args['version'] = version; + + if (typeof(args) == 'string'){ + req_data['args'] = JSON.stringify(toArrayObject(args)); + } else { + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/callback', req_data, function(data) { + layer.close(loadT); + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +//redis负载状态 start +function redisStatus(version) { + + redisPost('run_info',version, {},function(data){ + var rdata = $.parseJSON(data.data); + // if (!rdata.status){ + // layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + // return; + // } + + hit = (parseInt(rdata.keyspace_hits) / (parseInt(rdata.keyspace_hits) + parseInt(rdata.keyspace_misses)) * 100).toFixed(2); + var con = '
\ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ + \ +
字段当前值说明
uptime_in_days' + rdata.uptime_in_days + '已运行天数
tcp_port' + rdata.tcp_port + '当前监听端口
connected_clients' + rdata.connected_clients + '连接的客户端数量
used_memory_rss' + toSize(rdata.used_memory_rss) + 'Redis当前占用的系统内存总量
used_memory' + toSize(rdata.used_memory) + 'Redis当前已分配的内存总量
used_memory_peak' + toSize(rdata.used_memory_peak) + 'Redis历史分配内存的峰值
mem_fragmentation_ratio' + rdata.mem_fragmentation_ratio + '%内存碎片比率
total_connections_received' + rdata.total_connections_received + '运行以来连接过的客户端的总数量
total_commands_processed' + rdata.total_commands_processed + '运行以来执行过的命令的总数量
instantaneous_ops_per_sec' + rdata.instantaneous_ops_per_sec + '服务器每秒钟执行的命令数量
keyspace_hits' + rdata.keyspace_hits + '查找数据库键成功的次数
keyspace_misses' + rdata.keyspace_misses + '查找数据库键失败的次数
hit' + hit + '%查找数据库键命中率
latest_fork_usec' + rdata.latest_fork_usec + '最近一次 fork() 操作耗费的微秒数
'; + $(".soft-man-con").html(con); + }); +} +//redis负载状态 end + +//配置修改 +function getRedisConfig(version) { + redisPost('get_redis_conf', version,'',function(data){ + // console.log(data); + var rdata = $.parseJSON(data.data); + // console.log(rdata); + var mlist = ''; + for (var i = 0; i < rdata.length; i++) { + var w = '70' + if (rdata[i].name == 'error_reporting') w = '250'; + var ibody = ''; + switch (rdata[i].type) { + case 0: + var selected_1 = (rdata[i].value == 1) ? 'selected' : ''; + var selected_0 = (rdata[i].value == 0) ? 'selected' : ''; + ibody = '' + break; + case 1: + var selected_1 = (rdata[i].value == 'On') ? 'selected' : ''; + var selected_0 = (rdata[i].value == 'Off') ? 'selected' : ''; + ibody = '' + break; + } + mlist += '

' + rdata[i].name + '' + ibody + ', ' + rdata[i].ps + '

' + } + var phpCon = '
' + mlist + '\ +
\ +
\ +
' + $(".soft-man-con").html(phpCon); + }); +} + +//提交PHP配置 +function submitConf(version) { + var data = { + version: version, + bind: $("input[name='bind']").val(), + 'port': $("input[name='port']").val(), + 'timeout': $("input[name='timeout']").val(), + maxclients: $("input[name='maxclients']").val(), + databases: $("input[name='databases']").val(), + requirepass: $("input[name='requirepass']").val(), + maxmemory: $("input[name='maxmemory']").val(), + }; + + redisPost('submit_redis_conf', version, data, function(ret_data){ + var rdata = $.parseJSON(ret_data.data); + layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 }); + }); +} + diff --git a/plugins/tgbot/startup/extend/push_ad.py b/plugins/tgbot/startup/extend/push_ad.py index e049bd0a9..f26d6de1b 100644 --- a/plugins/tgbot/startup/extend/push_ad.py +++ b/plugins/tgbot/startup/extend/push_ad.py @@ -70,6 +70,8 @@ def send_msg(bot, tag='ad', trigger_time=300): text="🙎‍♂️代实名🙍‍♀️过人脸🅾️国际阿里云腾讯云(赞助商)", url='https://t.me/gjgzs2022') ], [ + types.InlineKeyboardButton( + text="倩倩CDN服务器", url='https://t.me/KLT_12'), types.InlineKeyboardButton( text="💎DigitalVirt(赞助商)", url='https://digitalvirt.com/aff.php?aff=154') ], diff --git a/plugins/tgbot/startup/extend/push_notice_msg.py b/plugins/tgbot/startup/extend/push_notice_msg.py index 5b866bcd4..763172976 100644 --- a/plugins/tgbot/startup/extend/push_notice_msg.py +++ b/plugins/tgbot/startup/extend/push_notice_msg.py @@ -66,6 +66,8 @@ def send_msg(bot, tag='ad', trigger_time=300): text="🙎‍♂️代实名🙍‍♀️过人脸🅾️国际阿里云腾讯云(赞助商)", url='https://t.me/gjgzs2022') ], [ + types.InlineKeyboardButton( + text="倩倩CDN服务器", url='https://t.me/KLT_12'), types.InlineKeyboardButton( text="💎DigitalVirt(赞助商)", url='https://digitalvirt.com/aff.php?aff=154') ],