diff --git a/plugins/mariadb/info.json b/plugins/mariadb/info.json index effaf5f8a8..5cbe1c638b 100755 --- a/plugins/mariadb/info.json +++ b/plugins/mariadb/info.json @@ -1,4 +1,5 @@ { + "sort":2, "hook":["database"], "title":"MariaDB", "tip":"soft", diff --git a/plugins/memcached/info.json b/plugins/memcached/info.json index 389213894c..0fde0fa720 100755 --- a/plugins/memcached/info.json +++ b/plugins/memcached/info.json @@ -1,5 +1,5 @@ { - "sort": 7, + "sort": 5, "ps": "是一个高性能的分布式内存对象缓存系统", "name": "memcached", "title": "Memcached", diff --git a/plugins/mongodb/info.json b/plugins/mongodb/info.json index 46b1478293..739a1e7a26 100755 --- a/plugins/mongodb/info.json +++ b/plugins/mongodb/info.json @@ -1,5 +1,5 @@ { - "sort": 7, + "sort":3, "hook":["database"], "ps": "一个高性能的NOSQL数据库【社区版】", "name": "mongodb", diff --git a/plugins/mysql/info.json b/plugins/mysql/info.json index 849b2b3ccb..4469f86fc7 100755 --- a/plugins/mysql/info.json +++ b/plugins/mysql/info.json @@ -1,4 +1,5 @@ { + "sort":1, "title":"MySQL", "tip":"soft", "name":"mysql", diff --git a/plugins/op_load_balance/info.json b/plugins/op_load_balance/info.json index 1855728783..695903c81a 100755 --- a/plugins/op_load_balance/info.json +++ b/plugins/op_load_balance/info.json @@ -1,4 +1,5 @@ { + "sort":3, "title":"OP负载均衡", "tip":"soft", "name":"op_load_balance", diff --git a/plugins/op_waf/info.json b/plugins/op_waf/info.json index 53b8509737..fe18198c72 100755 --- a/plugins/op_waf/info.json +++ b/plugins/op_waf/info.json @@ -11,6 +11,7 @@ } } ], + "sort":2, "title":"OP防火墙", "tip":"soft", "name":"op_waf", diff --git a/plugins/openresty/info.json b/plugins/openresty/info.json index 5f9e808aa2..5fb252408d 100755 --- a/plugins/openresty/info.json +++ b/plugins/openresty/info.json @@ -1,4 +1,5 @@ { + "sort": 0, "title":"OpenResty", "tip":"soft", "name":"openresty", diff --git a/plugins/php-guard/info.json b/plugins/php-guard/info.json index bd62f5eff7..6493c64f7b 100755 --- a/plugins/php-guard/info.json +++ b/plugins/php-guard/info.json @@ -1,5 +1,5 @@ { - "sort": 7, + "sort": 5, "ps": "监控PHP-FPM运行状态,防止大批量出现502错误!", "shell": "install.sh", "name": "php-guard", diff --git a/plugins/postgresql/info.json b/plugins/postgresql/info.json index ae9893a0cf..3fcd8c84bf 100755 --- a/plugins/postgresql/info.json +++ b/plugins/postgresql/info.json @@ -1,5 +1,6 @@ { "hook":["database"], + "sort": 6, "title":"PostgreSQL", "tip":"soft", "name":"postgresql", diff --git a/plugins/redis/index.py b/plugins/redis/index.py index 902006d5f6..08d2dbba0e 100755 --- a/plugins/redis/index.py +++ b/plugins/redis/index.py @@ -154,7 +154,7 @@ def initDreplace(): mw.execShell('chmod +x ' + file_bin) # config replace - dst_conf = getServerDir() + '/redis.conf' + dst_conf = getConf() dst_conf_init = getServerDir() + '/init.pl' if not os.path.exists(dst_conf_init): conf_content = mw.readFile(getConfTpl()) @@ -221,7 +221,7 @@ def reload(): def getPort(): - conf = getServerDir() + '/redis.conf' + conf = getConf() content = mw.readFile(conf) rep = r"^(port)\s*([.0-9A-Za-z_& ~]+)" @@ -234,7 +234,7 @@ def getPort(): def getRedisCmd(): requirepass = "" - conf = getServerDir() + '/redis.conf' + conf = getConf() content = mw.readFile(conf) rep = r"^(requirepass)\s*([.0-9A-Za-z_& ~]+)" tmp = re.search(rep, content, re.M) @@ -467,7 +467,7 @@ def runLog(): def getRedisConfInfo(): - conf = getServerDir() + '/redis.conf' + conf = getConf() gets = [ {'name': 'bind', 'type': 2, 'ps': '绑定IP(修改绑定IP可能会存在安全隐患)','must_show':1}, @@ -510,7 +510,7 @@ def submitRedisConf(): gets = ['bind', 'port', 'timeout', 'maxclients', 'databases', 'requirepass', 'maxmemory','slaveof','masterauth'] args = getArgs() - conf = getServerDir() + '/redis.conf' + conf = getConf() content = mw.readFile(conf) for g in gets: if g in args: diff --git a/plugins/redis/info.json b/plugins/redis/info.json index 9ede6b27ca..06ed3cc148 100755 --- a/plugins/redis/info.json +++ b/plugins/redis/info.json @@ -1,5 +1,5 @@ { - "sort": 7, + "sort":4, "ps": "一个高性能的KV数据库", "name": "redis", "title": "Redis", diff --git a/plugins/valkey/config/valkey.conf b/plugins/valkey/config/valkey.conf new file mode 100644 index 0000000000..e150cdc93c --- /dev/null +++ b/plugins/valkey/config/valkey.conf @@ -0,0 +1,90 @@ +daemonize yes +pidfile {$SERVER_PATH}/valkey/valkey.pid + +bind 127.0.0.1 +port 6389 +requirepass {$VALKEY_PASS} + +timeout 3 +tcp-keepalive 0 + +loglevel notice + +logfile {$SERVER_PATH}/valkey/data/valkey.log +databases 16 + +################################ SNAPSHOTTING ################################# + +save 900 1000 +save 300 10000 +save 60 1000000 +stop-writes-on-bgsave-error no +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir {$SERVER_PATH}/valkey/data/ + +################################# REPLICATION ################################# + +slave-serve-stale-data yes +slave-read-only yes + +repl-disable-tcp-nodelay no +slave-priority 100 + +################################## SECURITY ################################### + + +################################### LIMITS #################################### +maxclients 10000 +#maxmemory-samples 3 +maxmemory 218mb +maxmemory-policy volatile-ttl +#maxmemory-policy allkeys-lru + +############################## APPEND ONLY MODE ############################### + +# appendonly no + +# appendfsync always +# appendfsync everysec +# appendfsync no + +# appendfilename "appendonly.aof" + +no-appendfsync-on-rewrite no +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +################################ LUA SCRIPTING ############################### + +lua-time-limit 5000 + +################################## SLOW LOG ################################### + + +slowlog-log-slower-than 10000 +slowlog-max-len 128 + +############################### ADVANCED CONFIG ############################### + +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +set-max-intset-entries 512 + +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +activerehashing yes + +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +hz 10 + +aof-rewrite-incremental-fsync yes \ No newline at end of file diff --git a/plugins/valkey/ico.png b/plugins/valkey/ico.png new file mode 100644 index 0000000000..80a6300fd4 Binary files /dev/null and b/plugins/valkey/ico.png differ diff --git a/plugins/valkey/index.html b/plugins/valkey/index.html new file mode 100755 index 0000000000..894b2ffe69 --- /dev/null +++ b/plugins/valkey/index.html @@ -0,0 +1,36 @@ + + +
+
+
+
+

服务

+

自启动

+

配置修改

+ +

性能调整

+

负载状态

+

复制状态

+

集群状态

+

集群节点

+

运行日志

+

相关说明

+ +
+
+
+
+
+
+ \ No newline at end of file diff --git a/plugins/valkey/index.py b/plugins/valkey/index.py new file mode 100755 index 0000000000..11d175df90 --- /dev/null +++ b/plugins/valkey/index.py @@ -0,0 +1,570 @@ +# coding:utf-8 + +import sys +import io +import os +import time +import re + +web_dir = os.getcwd() + "/web" +if os.path.exists(web_dir): + sys.path.append(web_dir) + os.chdir(web_dir) + +import core.mw as mw + +app_debug = False +if mw.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'valkey' + + +def getPluginDir(): + return mw.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return mw.getServerDir() + '/' + getPluginName() + + +def getInitDFile(): + current_os = mw.getOs() + if current_os == 'darwin': + return '/tmp/' + getPluginName() + + if current_os.startswith('freebsd'): + return '/etc/rc.d/' + getPluginName() + + return '/etc/init.d/' + getPluginName() + + +def getConf(): + path = getServerDir() + "/valkey.conf" + return path + + +def getConfTpl(): + path = getPluginDir() + "/config/valkey.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 checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, mw.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, mw.returnJson(True, 'ok')) + +def configTpl(): + path = getPluginDir() + '/tpl' + pathFile = os.listdir(path) + tmp = [] + for one in pathFile: + file = path + '/' + one + tmp.append(file) + return mw.getJson(tmp) + + +def readConfigTpl(): + args = getArgs() + data = checkArgs(args, ['file']) + if not data[0]: + return data[1] + + content = mw.readFile(args['file']) + content = contentReplace(content) + return mw.returnJson(True, 'ok', content) + +def getPidFile(): + file = getConf() + content = mw.readFile(file) + rep = r'pidfile\s*(.*)' + tmp = re.search(rep, content) + return tmp.groups()[0].strip() + +def status(): + pid_file = getPidFile() + if not os.path.exists(pid_file): + return 'stop' + + # data = mw.execShell( + # "ps aux|grep redis |grep -v grep | grep -v python | grep -v mdserver-web | awk '{print $2}'") + + # if data[0] == '': + # return 'stop' + return 'start' + +def contentReplace(content): + service_path = mw.getServerDir() + content = content.replace('{$ROOT_PATH}', mw.getFatherDir()) + content = content.replace('{$SERVER_PATH}', service_path) + content = content.replace('{$SERVER_APP}', service_path + '/'+getPluginName()) + content = content.replace('{$VALKEY_PASS}', mw.getRandomString(10)) + return content + + + +def initDreplace(): + + file_tpl = getInitDTpl() + service_path = mw.getServerDir() + + 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('mkdir -p ' + dataLog) + mw.execShell('chmod +x ' + file_bin) + + # config replace + dst_conf = getConf() + dst_conf_init = getServerDir() + '/init.pl' + if not os.path.exists(dst_conf_init): + content = mw.readFile(getConfTpl()) + content = content.replace('{$SERVER_PATH}', service_path) + content = content.replace('{$VALKEY_PASS}', mw.getRandomString(10)) + + mw.writeFile(dst_conf, content) + mw.writeFile(dst_conf_init, 'ok') + + # systemd + systemDir = mw.systemdCfgDir() + systemService = systemDir + '/' + getPluginName() + '.service' + if os.path.exists(systemDir) and not os.path.exists(systemService): + systemServiceTpl = getPluginDir() + '/init.d/' + getPluginName() + '.service.tpl' + content = mw.readFile(systemServiceTpl) + content = content.replace('{$SERVER_PATH}', service_path) + mw.writeFile(systemService, content) + mw.execShell('systemctl daemon-reload') + + return file_bin + + +def wkOp(method): + file = initDreplace() + + current_os = mw.getOs() + if current_os == "darwin": + data = mw.execShell(file + ' ' + method) + if data[1] == '': + return 'ok' + return data[1] + + if current_os.startswith("freebsd"): + data = mw.execShell('service ' + getPluginName() + ' ' + method) + if data[1] == '': + return 'ok' + return data[1] + + data = mw.execShell('systemctl ' + method + ' ' + getPluginName()) + if data[1] == '': + return 'ok' + return data[1] + + +def start(): + return wkOp('start') + + +def stop(): + return wkOp('stop') + + +def restart(): + status = wkOp('restart') + + log_file = runLog() + mw.execShell("echo '' > " + log_file) + return status + + +def reload(): + return wkOp('reload') + + +def getPort(): + conf = getServerDir() + '/valkey.conf' + content = mw.readFile(conf) + + rep = r"^(port)\s*([.0-9A-Za-z_& ~]+)" + tmp = re.search(rep, content, re.M) + if tmp: + return tmp.groups()[1] + + return '6379' + + +def getRedisCmd(): + requirepass = "" + conf = getConf() + content = mw.readFile(conf) + rep = r"^(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' + port = getPort() + # findDebian = mw.execShell('cat /etc/issue |grep Debian') + # if findDebian[0] != '': + # default_ip = mw.getLocalIp() + cmd = getServerDir() + "/bin/valkey-cli -h " + default_ip + ' -p ' + port + " " + + if requirepass != "": + cmd = getServerDir() + '/bin/valkey-cli -h ' + default_ip + ' -p ' + port + ' -a "' + requirepass + '" ' + + return cmd + +def runInfo(): + s = status() + if s == 'stop': + return mw.returnJson(False, '未启动') + + + cmd = getRedisCmd() + cmd = cmd + '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 infoReplication(): + # 复制信息 + s = status() + if s == 'stop': + return mw.returnJson(False, '未启动') + + cmd = getRedisCmd() + cmd = cmd + 'info replication' + + # print(cmd) + data = mw.execShell(cmd)[0] + # print(data) + res = [ + #slave + 'role',#角色 + 'master_host', # 连接主库HOST + 'master_port', # 连接主库PORT + 'master_link_status', # 连接主库状态 + 'master_last_io_seconds_ago', # 上次同步时间 + 'master_sync_in_progress', # 正在同步中 + 'slave_read_repl_offset', # 从库读取复制位置 + 'slave_repl_offset', # 从库复制位置 + 'slave_priority', # 从库同步优先级 + 'slave_read_only', # 从库是否仅读 + 'replica_announced', # 已复制副本 + 'connected_slaves', # 连接从库数量 + 'master_failover_state', # 主库故障状态 + 'master_replid', # 主库复制ID + 'master_repl_offset', # 主库复制位置 + 'second_repl_offset', # 主库复制位置时间 + 'repl_backlog_active', # 复制状态 + 'repl_backlog_size', # 复制大小 + 'repl_backlog_first_byte_offset', # 第一个字节偏移量 + 'repl_backlog_histlen', # backlog中数据的长度 + ] + + 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] + + if 'role' in result and result['role'] == 'master': + connected_slaves = int(result['connected_slaves']) + slave_l = [] + for x in range(connected_slaves): + slave_l.append('slave'+str(x)) + + for d in data: + if len(d) < 3: + continue + t = d.strip().split(':') + if not t[0] in slave_l: + continue + result[t[0]] = t[1] + + return mw.getJson(result) + + +def clusterInfo(): + #集群信息 + # https://redis.io/commands/cluster-info/ + s = status() + if s == 'stop': + return mw.returnJson(False, '未启动') + + cmd = getRedisCmd() + cmd = cmd + 'cluster info' + + # print(cmd) + data = mw.execShell(cmd)[0] + # print(data) + + res = [ + 'cluster_state',#状态 + 'cluster_slots_assigned', # 被分配的槽 + 'cluster_slots_ok', # 被分配的槽状态 + 'cluster_slots_pfail', # 连接主库状态 + 'cluster_slots_fail', # 失败的槽 + 'cluster_known_nodes', # 知道的节点 + 'cluster_size', # 大小 + 'cluster_current_epoch', # + 'cluster_my_epoch', # + 'cluster_stats_messages_sent', # 发送 + 'cluster_stats_messages_received', # 接受 + 'total_cluster_links_buffer_limit_exceeded', # + ] + + 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 clusterNodes(): + s = status() + if s == 'stop': + return mw.returnJson(False, '未启动') + + cmd = getRedisCmd() + cmd = cmd + 'cluster nodes' + + # print(cmd) + data = mw.execShell(cmd)[0] + # print(data) + + data = data.strip().split("\n") + return mw.getJson(data) + +def initdStatus(): + current_os = mw.getOs() + if current_os == 'darwin': + return "Apple Computer does not support" + + if current_os.startswith('freebsd'): + initd_bin = getInitDFile() + if os.path.exists(initd_bin): + return 'ok' + + shell_cmd = 'systemctl status ' + \ + getPluginName() + ' | grep loaded | grep "enabled;"' + data = mw.execShell(shell_cmd) + if data[0] == '': + return 'fail' + return 'ok' + + +def initdInstall(): + current_os = mw.getOs() + if current_os == 'darwin': + return "Apple Computer does not support" + + # freebsd initd install + if current_os.startswith('freebsd'): + import shutil + source_bin = initDreplace() + initd_bin = getInitDFile() + shutil.copyfile(source_bin, initd_bin) + mw.execShell('chmod +x ' + initd_bin) + mw.execShell('sysrc ' + getPluginName() + '_enable="YES"') + return 'ok' + + mw.execShell('systemctl enable ' + getPluginName()) + return 'ok' + + +def initdUinstall(): + current_os = mw.getOs() + if current_os == 'darwin': + return "Apple Computer does not support" + + if current_os.startswith('freebsd'): + initd_bin = getInitDFile() + os.remove(initd_bin) + mw.execShell('sysrc ' + getPluginName() + '_enable="NO"') + return 'ok' + + mw.execShell('systemctl disable ' + getPluginName()) + return 'ok' + + +def runLog(): + return getServerDir() + '/data/valkey.log' + + +def getRedisConfInfo(): + conf = getConf() + + gets = [ + {'name': 'bind', 'type': 2, 'ps': '绑定IP(修改绑定IP可能会存在安全隐患)','must_show':1}, + {'name': 'port', 'type': 2, 'ps': '绑定端口','must_show':1}, + {'name': 'timeout', 'type': 2, 'ps': '空闲链接超时时间,0表示不断开','must_show':1}, + {'name': 'maxclients', 'type': 2, 'ps': '最大连接数','must_show':1}, + {'name': 'databases', 'type': 2, 'ps': '数据库数量','must_show':1}, + {'name': 'requirepass', 'type': 2, 'ps': 'redis密码,留空代表没有设置密码','must_show':1}, + {'name': 'maxmemory', 'type': 2, 'ps': 'MB,最大使用内存,0表示不限制','must_show':1}, + {'name': 'slaveof', 'type': 2, 'ps': '同步主库地址','must_show':0}, + {'name': 'masterauth', 'type': 2, 'ps': '同步主库密码', 'must_show':0} + ] + content = mw.readFile(conf) + + result = [] + for g in gets: + rep = r"^(" + g['name'] + r')\s*([.0-9A-Za-z_& ~]+)' + tmp = re.search(rep, content, re.M) + if not tmp: + if g['must_show'] == 0: + continue + + 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','slaveof','masterauth'] + args = getArgs() + conf = getConf() + content = mw.readFile(conf) + for g in gets: + if g in args: + rep = g + r'\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 == 'info_replication': + print(infoReplication()) + elif func == 'cluster_info': + print(clusterInfo()) + elif func == 'cluster_nodes': + print(clusterNodes()) + 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()) + elif func == 'config_tpl': + print(configTpl()) + elif func == 'read_config_tpl': + print(readConfigTpl()) + else: + print('error') diff --git a/plugins/valkey/info.json b/plugins/valkey/info.json new file mode 100755 index 0000000000..11b1cfeee8 --- /dev/null +++ b/plugins/valkey/info.json @@ -0,0 +1,17 @@ +{ + "sort": 8, + "ps": "一个高性能键值数据存储系统", + "name": "valkey", + "title": "valkey", + "shell": "install.sh", + "versions":["8.0.1"], + "tip": "soft", + "checks": "server/valkey", + "path": "server/valkey", + "display": 1, + "author": "valkey", + "date": "2024-12-08", + "home": "https://valkey.io/download/", + "type": 0, + "pid": "2" +} diff --git a/plugins/valkey/init.d/valkey.service.tpl b/plugins/valkey/init.d/valkey.service.tpl new file mode 100644 index 0000000000..ac2e6201bc --- /dev/null +++ b/plugins/valkey/init.d/valkey.service.tpl @@ -0,0 +1,12 @@ +[Unit] +Description=Redis In-Memory Data Store +After=network.target + +[Service] +Type=forking +ExecStart={$SERVER_PATH}/valkey/bin/valkey-server {$SERVER_PATH}/valkey/valkey.conf +ExecReload=/bin/kill -USR2 $MAINPID +Restart=on-failure + +[Install] +WantedBy=multi-user.target \ No newline at end of file diff --git a/plugins/valkey/init.d/valkey.tpl b/plugins/valkey/init.d/valkey.tpl new file mode 100644 index 0000000000..c2d01c3c29 --- /dev/null +++ b/plugins/valkey/init.d/valkey.tpl @@ -0,0 +1,78 @@ +#!/bin/sh +# chkconfig: 2345 55 25 +# description: Redis Service + +### BEGIN INIT INFO +# Provides: Redis +# Required-Start: $all +# Required-Stop: $all +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts Redis +# Description: starts the MDW-Web +### END INIT INFO + +# Simple Redis init.d script conceived to work on Linux systems +# as it does use of the /proc filesystem. + +CONF="{$SERVER_PATH}/valkey/valkey.conf" +REDISPORT=$(cat $CONF |grep port|grep -v '#'|awk '{print $2}') +REDISPASS=$(cat $CONF |grep requirepass|grep -v '#'|awk '{print $2}') +if [ "$REDISPASS" != "" ];then + REDISPASS=" -a $REDISPASS" +fi +EXEC={$SERVER_PATH}/valkey/bin/valkey-server +CLIEXEC="{$SERVER_PATH}/valkey/bin/valkey-cli -p $REDISPORT$REDISPASS" +PIDFILE={$SERVER_PATH}/valkey/valkey.pid + +echo $REDISPASS +echo $REDISPORT +echo $CLIEXEC + +mkdir -p {$SERVER_PATH}/valkey/data + +valkey_start(){ + if [ -f $PIDFILE ];then + kill -9 `cat $PIDFILE` + fi + + echo "Starting valkey server..." + nohup $EXEC $CONF >> {$SERVER_PATH}/valkey/logs.pl 2>&1 & +} + +valkey_stop(){ + if [ ! -f $PIDFILE ] + then + echo "$PIDFILE does not exist, process is not running" + else + PID=$(cat $PIDFILE) + echo "Stopping ..." + $CLIEXEC shutdown save 2>/dev/null + while [ -x /proc/${PID} ] + do + echo "Waiting for valkey to shutdown ..." + sleep 1 + done + echo "valkey stopped" + rm -rf $PIDFILE + fi +} + + +case "$1" in + start) + valkey_start + ;; + stop) + valkey_stop + ;; + restart|reload) + valkey_stop + sleep 0.3 + valkey_start + ;; + *) + echo "Please use start or stop as first argument" + ;; +esac + diff --git a/plugins/valkey/install.sh b/plugins/valkey/install.sh new file mode 100755 index 0000000000..a8343e137f --- /dev/null +++ b/plugins/valkey/install.sh @@ -0,0 +1,96 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin:/opt/homebrew/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") + +# https://www.cnblogs.com/zlonger/p/16177595.html +# https://www.cnblogs.com/BNTang/articles/15841688.html + +# ps -ef|grep valkey |grep -v grep | awk '{print $2}' | xargs kill + +# cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/valkey && bash install.sh install 7.2.2 + +# cmd查看| info replication +# /Users/midoks/Desktop/mwdev/server/valkey/bin/valkey-cli -h 127.0.0.1 -p 6399 +# /www/server/valkey/bin/valkey-cli -h 127.0.0.1 -p 6399 + +VERSION=$2 + +Install_App() +{ + echo '正在安装脚本文件...' + mkdir -p $serverPath/source + mkdir -p $serverPath/source/valkey + + FILE_TGZ=${VERSION}.tar.gz + VALKEY_DIR=$serverPath/source/valkey + + if [ ! -f $VALKEY_DIR/${FILE_TGZ} ];then + wget --no-check-certificate -O $VALKEY_DIR/${FILE_TGZ} https://github.com/valkey-io/valkey/archive/refs/tags/${FILE_TGZ} + fi + + cd $VALKEY_DIR && tar -zxvf ${FILE_TGZ} + + CMD_MAKE=`which gmake` + if [ "$?" == "0" ];then + cd valkey-${VERSION} && gmake PREFIX=$serverPath/valkey install + else + cd valkey-${VERSION} && make PREFIX=$serverPath/valkey install + fi + + if [ -d $serverPath/valkey ];then + mkdir -p $serverPath/valkey/data + sed '/^ *#/d' valkey.conf > $serverPath/valkey/valkey.conf + + echo "${VERSION}" > $serverPath/valkey/version.pl + echo '安装完成' + + cd ${rootPath} && python3 plugins/valkey/index.py start + cd ${rootPath} && python3 plugins/valkey/index.py initd_install + + else + echo '安装失败!' + fi + + if [ -d ${REDIS_DIR}/valkey-${VERSION} ];then + rm -rf ${REDIS_DIR}/valkey-${VERSION} + fi +} + +Uninstall_App() +{ + if [ -f /usr/lib/systemd/system/valkey.service ];then + systemctl stop valkey + systemctl disable valkey + rm -rf /usr/lib/systemd/system/valkey.service + systemctl daemon-reload + fi + + if [ -f /lib/systemd/system/valkey.service ];then + systemctl stop valkey + systemctl disable valkey + rm -rf /lib/systemd/system/valkey.service + systemctl daemon-reload + fi + + if [ -f $serverPath/valkey/initd/valkey ];then + $serverPath/valkey/initd/valkey stop + fi + + if [ -d $serverPath/valkey ];then + rm -rf $serverPath/valkey + fi + + echo "卸载valkey成功" +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_App +else + Uninstall_App +fi diff --git a/plugins/valkey/js/valkey.js b/plugins/valkey/js/valkey.js new file mode 100755 index 0000000000..9540415f42 --- /dev/null +++ b/plugins/valkey/js/valkey.js @@ -0,0 +1,297 @@ +function redisPost(method, version, args,callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + + var req_data = {}; + req_data['name'] = 'valkey'; + 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'] = 'valkey'; + 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 ('status' in rdata && !rdata.status){ + layer.msg(rdata.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); + }); +} + +function replStatus(version){ + redisPost('info_replication', version, {},function(data){ + var rdata = $.parseJSON(data.data); + + if ('status' in rdata && !rdata.status){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + var kv = { + 'role':'角色', + 'master_host':'连接主库HOST', + 'master_port':'连接主库PORT', + 'master_link_status':'连接主库状态', + 'master_last_io_seconds_ago':'上次同步时间', + 'master_sync_in_progress':'正在同步中', + 'slave_read_repl_offset':'从库读取复制位置', + 'slave_repl_offset':'从库复制位置', + 'slave_read_only':'从库是否仅读', + 'replica_announced':'已复制副本', + 'connected_slaves':'连接数量', + 'master_failover_state':'主库故障状态', + 'master_replid':'主库复制ID', + 'master_repl_offset':'主库复制位置', + 'repl_backlog_size':'backlog复制大小', + 'second_repl_offset':'复制位置时间', + 'repl_backlog_first_byte_offset':'第一个字节偏移量', + 'repl_backlog_histlen':'backlog中数据的长度', + 'repl_backlog_active':'开启复制缓冲区', + 'slave_priority':'同步优先级', + } + + var tbody_text = ''; + for (k in rdata){ + if (k == 'master_replid'){ + tbody_text += ''+k+'' + rdata[k] + ''+kv[k]+''; + } else{ + + if (k.substring(0,5) == 'slave' && !isNaN(k.substring(5))){ + tbody_text += ''+k+'' + rdata[k] + '从库配置信息'; + } else{ + tbody_text += ''+k+'' + rdata[k] + ''+kv[k]+''; + } + + + } + } + + var con = '
\ + \ + \ + '+tbody_text+'\ +
字段当前值说明
'; + $(".soft-man-con").html(con); + }); +} + +function clusterStatus(version){ + redisPost('cluster_info', version, {},function(data){ + var rdata = $.parseJSON(data.data); + + if ('status' in rdata && !rdata.status){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + var kv = { + 'cluster_state':'集群状态', + 'cluster_slots_assigned':'被分配的槽', + 'cluster_slots_ok':'被分配的槽状态', + 'cluster_known_nodes':'知道的节点', + 'cluster_size':'大小', + 'cluster_stats_messages_sent':'发送', + 'cluster_stats_messages_received':'接收', + 'cluster_current_epoch':'集群当前epoch', + 'cluster_my_epoch':'当前我的epoch', + 'cluster_slots_pfail':'处于PFAIL状态的槽数', + 'cluster_slots_fail':'处于FAIL状态的槽数', + 'total_cluster_links_buffer_limit_exceeded':'超出缓冲区总数', + } + + var tbody_text = ''; + for (k in rdata){ + var desc = k; + if (k in kv){ + desc = kv[k]; + } + + if (k == 'master_replid'){ + tbody_text += ''+k+'' + rdata[k] + ''+desc+''; + } else{ + tbody_text += ''+k+'' + rdata[k] + ''+desc+''; + } + } + + if (tbody_text == ''){ + tbody_text += '无数据/未设置集群'; + } + + var con = '
\ + \ + \ + '+tbody_text+'\ +
字段当前值说明
'; + $(".soft-man-con").html(con); + }); +} + +function clusterNodes(version){ + redisPost('cluster_nodes', version, {},function(data){ + var rdata = $.parseJSON(data.data); + + if ('status' in rdata && !rdata.status){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + // console.log(rdata); + var tbody_text = ''; + for (k in rdata){ + tbody_text += ''+ rdata[k] +''; + } + + if (tbody_text == ''){ + tbody_text += '无数据/未设置集群'; + } + + var con = '
\ + \ + \ + '+tbody_text+'\ +
节点信息
'; + $(".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 con = '
' + mlist + '\ +
\ +
\ +
' + $(".soft-man-con").html(con); + }); +} + +//提交配置 +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 }); + }); +} + + +function valkeyReadme(){ + var cmd_01 = '/www/server/valkey/bin/valkey-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 --cluster-replicas 0'; + var cmd_02 = '/www/server/valkey/bin/valkey-cli --cluster create 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384 --cluster-replicas 1'; + + + var readme = ''; + + $('.soft-man-con').html(readme); +} + diff --git a/plugins/valkey/tpl/valkey_cluster.conf b/plugins/valkey/tpl/valkey_cluster.conf new file mode 100644 index 0000000000..100d86cef5 --- /dev/null +++ b/plugins/valkey/tpl/valkey_cluster.conf @@ -0,0 +1,94 @@ +daemonize yes +pidfile {$SERVER_PATH}/valkey/valkey.pid + +loglevel notice +logfile {$SERVER_PATH}/valkey/data/valkey.log +databases 16 + +timeout 0 +tcp-keepalive 0 + +bind 127.0.0.1 +port 6379 + +################################ SNAPSHOTTING ################################# + +save 900 100 +save 300 1000 +save 60 1000000 +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir {$SERVER_PATH}/valkey/data/ + +################################# CLUSTER ################################# + + +protected-mode no +cluster-enabled yes +cluster-config-file nodes_{$REDIS_PASS}.conf +cluster-require-full-coverage no +cluster-node-timeout 15000 + +################################# REPLICATION ################################# + +slave-serve-stale-data yes +slave-read-only yes + +repl-disable-tcp-nodelay no +slave-priority 100 + +################################## SECURITY ################################### + + +################################### LIMITS #################################### +maxclients 10000 +#maxmemory-samples 3 +maxmemory 218mb +maxmemory-policy volatile-ttl + +############################## APPEND ONLY MODE ############################### + + +#appendonly no +# appendfsync always +#appendfsync everysec +# appendfsync no +#no-appendfsync-on-rewrite no + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +################################ LUA SCRIPTING ############################### + +lua-time-limit 5000 + +################################## SLOW LOG ################################### + + +slowlog-log-slower-than 10000 +slowlog-max-len 128 + +############################### ADVANCED CONFIG ############################### + +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +set-max-intset-entries 512 + +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +activerehashing yes + +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +hz 10 + +aof-rewrite-incremental-fsync yes \ No newline at end of file diff --git a/plugins/valkey/tpl/valkey_simple.conf b/plugins/valkey/tpl/valkey_simple.conf new file mode 100644 index 0000000000..ba0e9ae21b --- /dev/null +++ b/plugins/valkey/tpl/valkey_simple.conf @@ -0,0 +1,87 @@ +daemonize yes +pidfile {$SERVER_PATH}/valkey/valkey.pid + +bind 127.0.0.1 +port 6379 +requirepass {$VALKEY_PASS} + +timeout 0 +tcp-keepalive 0 + +loglevel notice + +logfile {$SERVER_PATH}/valkey/data/valkey.log +databases 16 + +################################ SNAPSHOTTING ################################# + +save 900 100 +save 300 1000 +save 60 1000000 +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir {$SERVER_PATH}/valkey/data/ + +################################# REPLICATION ################################# + +slave-serve-stale-data yes +slave-read-only yes + +repl-disable-tcp-nodelay no +slave-priority 100 + +################################## SECURITY ################################### + + +################################### LIMITS #################################### +maxclients 10000 +#maxmemory-samples 3 +maxmemory 218mb +maxmemory-policy volatile-ttl + +############################## APPEND ONLY MODE ############################### + + +#appendonly no +# appendfsync always +#appendfsync everysec +# appendfsync no +#no-appendfsync-on-rewrite no + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +################################ LUA SCRIPTING ############################### + +lua-time-limit 5000 + +################################## SLOW LOG ################################### + + +slowlog-log-slower-than 10000 +slowlog-max-len 128 + +############################### ADVANCED CONFIG ############################### + +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +set-max-intset-entries 512 + +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +activerehashing yes + +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +hz 10 + +aof-rewrite-incremental-fsync yes \ No newline at end of file diff --git a/plugins/valkey/tpl/valkey_slave.conf b/plugins/valkey/tpl/valkey_slave.conf new file mode 100644 index 0000000000..de91840303 --- /dev/null +++ b/plugins/valkey/tpl/valkey_slave.conf @@ -0,0 +1,91 @@ +daemonize yes +pidfile {$SERVER_PATH}/valkey/valkey.pid + +bind 127.0.0.1 +port 6379 +requirepass {$VALKEY_PASS} + +timeout 0 +tcp-keepalive 0 + +loglevel notice + +logfile {$SERVER_PATH}/valkey/data/valkey.log +databases 16 + +################################ SNAPSHOTTING ################################# + +save 900 100 +save 300 1000 +save 60 1000000 +stop-writes-on-bgsave-error yes +rdbcompression yes +rdbchecksum yes +dbfilename dump.rdb +dir {$SERVER_PATH}/valkey/data/ + +################################# REPLICATION ################################# + +slave-serve-stale-data yes +slave-read-only yes + +repl-disable-tcp-nodelay no +slave-priority 100 + +# 填写主库信息 +#slaveof 127.0.0.1 6379 +#masterauth 123123 + +################################## SECURITY ################################### + + +################################### LIMITS #################################### +maxclients 10000 +#maxmemory-samples 3 +maxmemory 0mb +maxmemory-policy volatile-ttl + +############################## APPEND ONLY MODE ############################### + + +#appendonly no +# appendfsync always +#appendfsync everysec +# appendfsync no +#no-appendfsync-on-rewrite no + +auto-aof-rewrite-percentage 100 +auto-aof-rewrite-min-size 64mb + +################################ LUA SCRIPTING ############################### + +lua-time-limit 5000 + +################################## SLOW LOG ################################### + + +slowlog-log-slower-than 10000 +slowlog-max-len 128 + +############################### ADVANCED CONFIG ############################### + +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +set-max-intset-entries 512 + +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +activerehashing yes + +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +hz 10 + +aof-rewrite-incremental-fsync yes \ No newline at end of file diff --git a/plugins/valkey/tpl/valkey_slave_mem.conf b/plugins/valkey/tpl/valkey_slave_mem.conf new file mode 100644 index 0000000000..baf66f54fa --- /dev/null +++ b/plugins/valkey/tpl/valkey_slave_mem.conf @@ -0,0 +1,75 @@ +daemonize yes +pidfile {$SERVER_PATH}/valkey/valkey.pid + +loglevel notice +logfile {$SERVER_PATH}/valkey/data/valkey.log +databases 16 + +timeout 0 +tcp-keepalive 0 + +bind 127.0.0.1 +port 6379 +requirepass {$VALKEY_PASS} + +################################ SNAPSHOTTING ################################# + +save "" +stop-writes-on-bgsave-error no + +################################# REPLICATION ################################# + +slave-serve-stale-data yes +slave-read-only yes + +repl-disable-tcp-nodelay no +slave-priority 100 + +# 填写主库信息 +#slaveof 127.0.0.1 6379 +#masterauth 123123 + +################################## SECURITY ################################### + + +################################### LIMITS #################################### +maxclients 10000 +#maxmemory-samples 3 +maxmemory 218mb +maxmemory-policy allkeys-lru + +############################## APPEND ONLY MODE ############################### + + +################################ LUA SCRIPTING ############################### + +lua-time-limit 5000 + +################################## SLOW LOG ################################### + + +slowlog-log-slower-than 10000 +slowlog-max-len 128 + +############################### ADVANCED CONFIG ############################### + +hash-max-ziplist-entries 512 +hash-max-ziplist-value 64 + +list-max-ziplist-entries 512 +list-max-ziplist-value 64 + +set-max-intset-entries 512 + +zset-max-ziplist-entries 128 +zset-max-ziplist-value 64 + +activerehashing no + +client-output-buffer-limit normal 0 0 0 +client-output-buffer-limit slave 256mb 64mb 60 +client-output-buffer-limit pubsub 32mb 8mb 60 + +hz 10 + +aof-rewrite-incremental-fsync yes \ No newline at end of file diff --git a/plugins/webstats/info.json b/plugins/webstats/info.json index 5d31a1cdc5..0eadd5e46a 100755 --- a/plugins/webstats/info.json +++ b/plugins/webstats/info.json @@ -11,7 +11,7 @@ } } ], - "sort": "7", + "sort": "2", "ps": "网站统计报表", "name": "webstats", "title": "网站统计", diff --git a/plugins/xhprof/info.json b/plugins/xhprof/info.json index 1a4f01d418..f93d855316 100755 --- a/plugins/xhprof/info.json +++ b/plugins/xhprof/info.json @@ -1,4 +1,5 @@ { + "sort": 4, "title":"xhprof", "tip":"soft", "name":"xhprof", diff --git a/web/static/app/public.js b/web/static/app/public.js index 8221d763aa..dd3436f0f1 100755 --- a/web/static/app/public.js +++ b/web/static/app/public.js @@ -2253,6 +2253,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_ pluginConfigSave(fileName,save_callback_func); } + var fileName = ''; $.post('/plugins/run',{name:_name, func:_config_tpl_func,version:version}, function(data){ var rdata = $.parseJSON(data.data); @@ -2266,6 +2267,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_ var loadT = layer.msg('配置模版获取中...',{icon:16,time:0,shade: [0.3, '#000']}); var _args = JSON.stringify({file:selected}); + $.post('/plugins/run', {name:_name, func:_read_config_tpl_func,version:version,args:_args}, function(data){ layer.close(loadT); @@ -2275,9 +2277,13 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_ return; } + + $("#textBody").empty().text(rdata.data); $(".CodeMirror").remove(); editor = CodeMirror.fromTextArea(document.getElementById("textBody"), { + lineNumbers: true, + matchBrackets:true, extraKeys: { "Ctrl-Space": "autocomplete", "Ctrl-F": "findPersistent", @@ -2288,15 +2294,12 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_ "Cmd-S":function() { saveDataFunc(); } - }, - lineNumbers: true, - matchBrackets:true, + } }); editor.focus(); $(".CodeMirror-scroll").css({"height":"300px","margin":0,"padding":0}); - $("#onlineEditFileBtn").unbind('click'); - $("#onlineEditFileBtn").click(function(){ - saveDataFunc() + $("#onlineEditFileBtn").unbind('click').click(function(){ + saveDataFunc(); }); },'json'); } @@ -2318,7 +2321,7 @@ function pluginConfigTpl(_name, version, func, config_tpl_func, read_config_tpl_ } $("#textBody").empty().text(rdata.data.data); $(".CodeMirror").remove(); - var editor = CodeMirror.fromTextArea(document.getElementById("textBody"), { + editor = CodeMirror.fromTextArea(document.getElementById("textBody"), { extraKeys: { "Ctrl-Space": "autocomplete", "Ctrl-F": "findPersistent", diff --git a/web/utils/plugin.py b/web/utils/plugin.py index 306941a128..ad40d47f46 100644 --- a/web/utils/plugin.py +++ b/web/utils/plugin.py @@ -444,6 +444,7 @@ def makePluginInfo(self, info): pInfo = { "id": 10000, + "sort": 10000, "pid": info['pid'], "type": 1000, "name": info['name'], @@ -470,6 +471,9 @@ def makePluginInfo(self, info): if 'icon' in info: pInfo['icon'] = info['icon'] + if 'sort' in info: + pInfo['sort'] = info['sort'] + if checks.find('VERSION') > -1: pInfo['install_checks'] = checks.replace('VERSION', info['versions']) @@ -689,6 +693,8 @@ def getAllPluginList( for index in range(len(t)): info.append(t[index]) + info = sorted(info, key=lambda f: int(f['sort']), reverse=False) + start = (page - 1) * size end = start + size x = info[start:end] diff --git a/web/version.py b/web/version.py index e78644ee3f..e6e3fa0d24 100644 --- a/web/version.py +++ b/web/version.py @@ -13,7 +13,7 @@ # 应用程序版本号组件 APP_RELEASE = 0 APP_REVISION = 18 -APP_SMALL_VERSION = 0 +APP_SMALL_VERSION = 1 # 应用程序版本后缀,例如“beta1”、“dev”。通常为空字符串GA发布 APP_SUFFIX = ''