diff --git a/plugins/sphinx/ico.png b/plugins/sphinx/ico.png
new file mode 100644
index 000000000..9ddb87aa3
Binary files /dev/null and b/plugins/sphinx/ico.png differ
diff --git a/plugins/sphinx/index.html b/plugins/sphinx/index.html
new file mode 100755
index 000000000..4af4424b3
--- /dev/null
+++ b/plugins/sphinx/index.html
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/plugins/sphinx/index.py b/plugins/sphinx/index.py
new file mode 100755
index 000000000..f50457221
--- /dev/null
+++ b/plugins/sphinx/index.py
@@ -0,0 +1,218 @@
+# coding:utf-8
+
+import sys
+import io
+import os
+import time
+
+sys.path.append(os.getcwd() + "/class/core")
+import public
+
+app_debug = False
+if public.isAppleSystem():
+ app_debug = True
+
+
+def getPluginName():
+ return 'sphinx'
+
+
+def getPluginDir():
+ return public.getPluginDir() + '/' + getPluginName()
+
+
+def getServerDir():
+ return public.getServerDir() + '/' + getPluginName()
+
+
+def getInitDFile():
+ if app_debug:
+ return '/tmp/' + getPluginName()
+ return '/etc/init.d/' + getPluginName()
+
+
+def getConf():
+ path = getPluginDir() + "/config/redis.conf"
+ return path
+
+
+def getInitDTpl():
+ path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
+ return path
+
+
+def getArgs():
+ args = sys.argv[2:]
+ tmp = {}
+ args_len = len(args)
+
+ if args_len == 1:
+ t = args[0].strip('{').strip('}')
+ t = t.split(':')
+ 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 = public.execShell(
+ "ps -ef|grep redis |grep -v grep | grep -v python | 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
+ content = public.readFile(file_tpl)
+ content = content.replace('{$SERVER_PATH}', service_path)
+ public.writeFile(file_bin, content)
+ public.execShell('chmod +x ' + file_bin)
+
+ # config replace
+ conf_content = public.readFile(getConf())
+ conf_content = conf_content.replace('{$SERVER_PATH}', service_path)
+ public.writeFile(getServerDir() + '/redis.conf', conf_content)
+
+ return file_bin
+
+
+def start():
+ file = initDreplace()
+ data = public.execShell(file + ' start')
+ if data[1] == '':
+ return 'ok'
+ return 'fail'
+
+
+def stop():
+ file = initDreplace()
+ data = public.execShell(file + ' stop')
+ if data[1] == '':
+ return 'ok'
+ return 'fail'
+
+
+def restart():
+ file = initDreplace()
+ data = public.execShell(file + ' restart')
+ if data[1] == '':
+ return 'ok'
+ return 'fail'
+
+
+def reload():
+ file = initDreplace()
+ data = public.execShell(file + ' reload')
+ if data[1] == '':
+ return 'ok'
+ return 'fail'
+
+
+def runInfo():
+ cmd = getServerDir() + "/bin/redis-cli info"
+ data = public.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 public.getJson(result)
+
+
+def initdStatus():
+ if not app_debug:
+ os_name = public.getOs()
+ if os_name == 'darwin':
+ return "Apple Computer does not support"
+ initd_bin = getInitDFile()
+ if os.path.exists(initd_bin):
+ return 'ok'
+ return 'fail'
+
+
+def initdInstall():
+ import shutil
+ if not app_debug:
+ os_name = public.getOs()
+ if os_name == 'darwin':
+ return "Apple Computer does not support"
+
+ source_bin = initDreplace()
+ initd_bin = getInitDFile()
+ shutil.copyfile(source_bin, initd_bin)
+ public.execShell('chmod +x ' + initd_bin)
+ return 'ok'
+
+
+def initdUinstall():
+ if not app_debug:
+ os_name = public.getOs()
+ if os_name == 'darwin':
+ return "Apple Computer does not support"
+ initd_bin = getInitDFile()
+ os.remove(initd_bin)
+ return 'ok'
+
+
+def runLog():
+ return getServerDir() + '/data/redis.log'
+
+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()
+ else:
+ print 'error'
diff --git a/plugins/sphinx/info.json b/plugins/sphinx/info.json
new file mode 100755
index 000000000..87238bd7f
--- /dev/null
+++ b/plugins/sphinx/info.json
@@ -0,0 +1,17 @@
+{
+ "sort": 7,
+ "ps": "简单高效的全文搜索引擎",
+ "name": "sphinx",
+ "title": "sphinx",
+ "shell": "install.sh",
+ "versions":["4.0"],
+ "updates":["4.0.11"],
+ "tip": "soft",
+ "checks": "server/sphinx",
+ "display": 1,
+ "author": "midoks",
+ "date": "2017-04-01",
+ "home": "http://sphinxsearch.com/",
+ "type": 0,
+ "pid": "5"
+}
\ No newline at end of file
diff --git a/plugins/sphinx/install.sh b/plugins/sphinx/install.sh
new file mode 100755
index 000000000..aca61f0c9
--- /dev/null
+++ b/plugins/sphinx/install.sh
@@ -0,0 +1,35 @@
+#!/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/bt_install.pl
+
+
+Install_sphinx()
+{
+
+ echo '正在安装脚本文件...' > $install_tmp
+ mkdir -p $serverPath/sphinx
+
+ echo '4.0' > $serverPath/sphinx/version.pl
+ echo '安装完成' > $install_tmp
+}
+
+Uninstall_sphinx()
+{
+ rm -rf $serverPath/sphinx
+ echo "Uninstall_sphinx" > $install_tmp
+}
+
+action=$1
+if [ "${1}" == 'install' ];then
+ Install_sphinx
+else
+ Uninstall_sphinx
+fi
diff --git a/plugins/sphinx/js/sphinx.js b/plugins/sphinx/js/sphinx.js
new file mode 100755
index 000000000..784349ab9
--- /dev/null
+++ b/plugins/sphinx/js/sphinx.js
@@ -0,0 +1,479 @@
+
+function str2Obj(str){
+ var data = {};
+ kv = str.split('&');
+ for(i in kv){
+ v = kv[i].split('=');
+ data[v[0]] = v[1];
+ }
+ return data;
+}
+
+function phpPost(method, version, args,callback){
+ var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
+
+ var req_data = {};
+ req_data['name'] = 'php';
+ req_data['func'] = method;
+ req_data['version'] = version;
+
+ if (typeof(args) == 'string'){
+ req_data['args'] = JSON.stringify(str2Obj(args));
+ } else {
+ req_data['args'] = JSON.stringify(args);
+ }
+
+ $.post('/plugins/run', 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');
+}
+
+
+//配置修改
+function phpSetConfig(version) {
+ phpPost('get_php_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,
+ display_errors: $("select[name='display_errors']").val(),
+ 'cgi.fix_pathinfo': $("select[name='cgi.fix_pathinfo']").val(),
+ 'date.timezone': $("input[name='date.timezone']").val(),
+ short_open_tag: $("select[name='short_open_tag']").val(),
+ asp_tags: $("select[name='asp_tags']").val() || 'On',
+ safe_mode: $("select[name='safe_mode']").val(),
+ max_execution_time: $("input[name='max_execution_time']").val(),
+ max_input_time: $("input[name='max_input_time']").val(),
+ memory_limit: $("input[name='memory_limit']").val(),
+ post_max_size: $("input[name='post_max_size']").val(),
+ file_uploads: $("select[name='file_uploads']").val(),
+ upload_max_filesize: $("input[name='upload_max_filesize']").val(),
+ max_file_uploads: $("input[name='max_file_uploads']").val(),
+ default_socket_timeout: $("input[name='default_socket_timeout']").val(),
+ error_reporting: $("input[name='error_reporting']").val() || 'On'
+ };
+
+ phpPost('submit_php_conf', version, data, function(ret_data){
+ var rdata = $.parseJSON(ret_data.data);
+ // console.log(rdata);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ });
+}
+
+
+
+//php上传限制
+function phpUploadLimitReq(version){
+ phpPost('get_limit_conf', version, '', function(ret_data){
+ var rdata = $.parseJSON(ret_data.data);
+ phpUploadLimit(version,rdata['max']);
+ });
+}
+
+function phpUploadLimit(version,max){
+ var LimitCon = 'MB
';
+ $(".soft-man-con").html(LimitCon);
+}
+
+
+//php超时限制
+function phpTimeLimitReq(version){
+ phpPost('get_limit_conf', version, '', function(ret_data){
+ var rdata = $.parseJSON(ret_data.data);
+ phpTimeLimit(version,rdata['maxTime']);
+ });
+}
+
+function phpTimeLimit(version, max) {
+ var LimitCon = '秒
';
+ $(".soft-man-con").html(LimitCon);
+}
+
+//设置超时限制
+function setPHPMaxTime(version) {
+ var max = $(".phpTimeLimit").val();
+ phpPost('set_max_time',version,{'time':max},function(data){
+ var rdata = $.parseJSON(data.data);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ });
+}
+//设置PHP上传限制
+function setPHPMaxSize(version) {
+ max = $(".phpUploadLimit").val();
+ if (max < 2) {
+ alert(max);
+ layer.msg('上传大小限制不能小于2M', { icon: 2 });
+ return;
+ }
+
+ phpPost('set_max_size',version,{'max':max},function(data){
+ var rdata = $.parseJSON(data.data);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ });
+}
+
+
+function getFpmConfig(version){
+ phpPost('get_fpm_conf', version, {}, function(data){
+ // console.log(data);
+ var rdata = $.parseJSON(data.data);
+ // console.log(rdata);
+ var limitList = "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ "" +
+ ""
+ var pms = [{ 'name': 'static', 'title': '静态' }, { 'name': 'dynamic', 'title': '动态' }];
+ var pmList = '';
+ for (var i = 0; i < pms.length; i++) {
+ pmList += '';
+ }
+ var body = "" +
+ "
并发方案:
" +
+ "
运行模式:*PHP-FPM运行模式
" +
+ "
max_children:*允许创建的最大子进程数
" +
+ "
start_servers: *起始进程数(服务启动后初始进程数量)
" +
+ "
min_spare_servers: *最小空闲进程数(清理空闲进程后的保留数量)
" +
+ "
max_spare_servers: *最大空闲进程数(当空闲进程达到此值时清理)
" +
+ "
" +
+ "
";
+
+ $(".soft-man-con").html(body);
+ $("select[name='limit']").change(function() {
+ var type = $(this).val();
+ var max_children = rdata.max_children;
+ var start_servers = rdata.start_servers;
+ var min_spare_servers = rdata.min_spare_servers;
+ var max_spare_servers = rdata.max_spare_servers;
+ switch (type) {
+ case '1':
+ max_children = 30;
+ start_servers = 5;
+ min_spare_servers = 5;
+ max_spare_servers = 20;
+ break;
+ case '2':
+ max_children = 50;
+ start_servers = 15;
+ min_spare_servers = 15;
+ max_spare_servers = 35;
+ break;
+ case '3':
+ max_children = 100;
+ start_servers = 20;
+ min_spare_servers = 20;
+ max_spare_servers = 70;
+ break;
+ case '4':
+ max_children = 200;
+ start_servers = 25;
+ min_spare_servers = 25;
+ max_spare_servers = 150;
+ break;
+ case '5':
+ max_children = 300;
+ start_servers = 30;
+ min_spare_servers = 30;
+ max_spare_servers = 180;
+ break;
+ case '6':
+ max_children = 500;
+ start_servers = 35;
+ min_spare_servers = 35;
+ max_spare_servers = 250;
+ break;
+ }
+
+ $("input[name='max_children']").val(max_children);
+ $("input[name='start_servers']").val(start_servers);
+ $("input[name='min_spare_servers']").val(min_spare_servers);
+ $("input[name='max_spare_servers']").val(max_spare_servers);
+ });
+ });
+}
+
+function setFpmConfig(version){
+ var max_children = Number($("input[name='max_children']").val());
+ var start_servers = Number($("input[name='start_servers']").val());
+ var min_spare_servers = Number($("input[name='min_spare_servers']").val());
+ var max_spare_servers = Number($("input[name='max_spare_servers']").val());
+ var pm = $("select[name='pm']").val();
+
+ if (max_children < max_spare_servers) {
+ layer.msg('max_spare_servers 不能大于 max_children', { icon: 2 });
+ return;
+ }
+
+ if (min_spare_servers > start_servers) {
+ layer.msg('min_spare_servers 不能大于 start_servers', { icon: 2 });
+ return;
+ }
+
+ if (max_spare_servers < min_spare_servers) {
+ layer.msg('min_spare_servers 不能大于 max_spare_servers', { icon: 2 });
+ return;
+ }
+
+ if (max_children < start_servers) {
+ layer.msg('start_servers 不能大于 max_children', { icon: 2 });
+ return;
+ }
+
+ if (max_children < 1 || start_servers < 1 || min_spare_servers < 1 || max_spare_servers < 1) {
+ layer.msg('配置值不能小于1', { icon: 2 });
+ return;
+ }
+
+ var data = {
+ version:version,
+ max_children:max_children,
+ start_servers:start_servers,
+ min_spare_servers:min_spare_servers,
+ max_spare_servers:max_spare_servers,
+ pm:pm,
+ };
+ phpPost('set_fpm_conf', version, data, function(ret_data){
+ var rdata = $.parseJSON(ret_data.data);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ });
+}
+
+
+function getFpmStatus(version){
+ phpPost('get_fpm_status', version, '', function(ret_data){
+ var rdata = $.parseJSON(ret_data.data);
+ var con = "\
+ 应用池(pool) | " + rdata.pool + " |
\
+ 进程管理方式(process manager) | " + ((rdata['process manager'] == 'dynamic') ? '动态' : '静态') + " |
\
+ 启动日期(start time) | " + rdata['start time'] + " |
\
+ 请求数(accepted conn) | " + rdata['accepted conn'] + " |
\
+ 请求队列(listen queue) | " + rdata['listen queue'] + " |
\
+ 最大等待队列(max listen queue) | " + rdata['max listen queue'] + " |
\
+ socket队列长度(listen queue len) | " + rdata['listen queue len'] + " |
\
+ 空闲进程数量(idle processes) | " + rdata['idle processes'] + " |
\
+ 活跃进程数量(active processes) | " + rdata['active processes'] + " |
\
+ 总进程数量(total processes) | " + rdata['total processes'] + " |
\
+ 最大活跃进程数量(max active processes) | " + rdata['max active processes'] + " |
\
+ 到达进程上限次数(max children reached) | " + rdata['max children reached'] + " |
\
+ 慢请求数量(slow requests) | " + rdata['slow requests'] + " |
\
+
";
+ $(".soft-man-con").html(con);
+ $(".GetPHPStatus td,.GetPHPStatus th").css("padding", "7px");
+ });
+}
+
+//禁用函数
+function disableFunc(version) {
+ phpPost('get_disable_func', version,'',function(data){
+ var rdata = $.parseJSON(data.data);
+ var disable_functions = rdata.disable_functions.split(',');
+ var dbody = ''
+ for (var i = 0; i < disable_functions.length; i++) {
+ if (disable_functions[i] == '') continue;
+ dbody += "" + disable_functions[i] + " | 删除 |
";
+ }
+
+ var con = "" +
+ "" +
+ "" +
+ "
" +
+ "" +
+ "名称 | 操作 |
" +
+ "" + dbody + "" +
+ "
";
+
+ con += '\
+ - 在此处可以禁用指定函数的调用,以增强环境安全性!
\
+ - 强烈建议禁用如exec,system等危险函数!
\
+
';
+
+ $(".soft-man-con").html(con);
+ });
+}
+//设置禁用函数
+function setDisableFunc(version, act, fs) {
+ var fsArr = fs.split(',');
+ if (act == 1) {
+ var functions = $("#disable_function_val").val();
+ for (var i = 0; i < fsArr.length; i++) {
+ if (functions == fsArr[i]) {
+ layer.msg(lan.soft.fun_msg, { icon: 5 });
+ return;
+ }
+ }
+ fs += ',' + functions;
+ msg = '添加成功';
+ } else {
+
+ fs = '';
+ for (var i = 0; i < fsArr.length; i++) {
+ if (act == fsArr[i]) continue;
+ fs += fsArr[i] + ','
+ }
+ msg = '删除成功';
+ fs = fs.substr(0, fs.length - 1);
+ }
+
+ var data = {
+ 'version':version,
+ 'disable_functions':fs,
+ };
+
+ phpPost('set_disable_func', version,data,function(data){
+ var rdata = $.parseJSON(data.data);
+ showMsg(rdata.status ? msg : rdata.msg, function(){
+ disableFunc(version);
+ } ,{ icon: rdata.status ? 1 : 2 });
+ });
+}
+
+
+//phpinfo
+function getPhpinfo(version) {
+ var con = '';
+ $(".soft-man-con").html(con);
+}
+
+//获取PHPInfo
+function getPHPInfo(version) {
+ phpPost('get_phpinfo', version, '', function(data){
+ var rdata = data.data;
+ layer.open({
+ type: 1,
+ title: "PHP-" + version + "-PHPINFO",
+ area: ['90%', '90%'],
+ closeBtn: 2,
+ shadeClose: true,
+ content: rdata
+ });
+ });
+}
+
+function phpLibConfig(version){
+
+ phpPost('get_lib_conf', version, '', function(data){
+ var rdata = $.parseJSON(data.data);
+ var libs = rdata.data;
+
+ var body = '';
+ var opt = '';
+ for (var i = 0; i < libs.length; i++) {
+ if (libs[i].versions.indexOf(version) == -1){
+ continue;
+ }
+
+ if (libs[i]['task'] == '-1' && libs[i].phpversions.indexOf(version) != -1) {
+ opt = '安装'
+ } else if (libs[i]['task'] == '0' && libs[i].phpversions.indexOf(version) != -1) {
+ opt = '等待安装...'
+ } else if (libs[i].status) {
+ opt = '卸载'
+ } else {
+ opt = '安装'
+ }
+
+ body += '' +
+ '' + libs[i].name + ' | ' +
+ '' + libs[i].type + ' | ' +
+ '' + libs[i].msg + ' | ' +
+ ' | ' +
+ '' + opt + ' | ' +
+ '
';
+ }
+
+
+ var con = '' +
+ '
' +
+ '' +
+ '' +
+ '名称 | ' +
+ '类型 | ' +
+ '说明 | ' +
+ '状态 | ' +
+ '操作 | ' +
+ '
' +
+ '' +
+ '' + body + '' +
+ '
' +
+ '
' +
+ '\
+ - 请按实际需求安装扩展,不要安装不必要的PHP扩展,这会影响PHP执行效率,甚至出现异常
\
+ - Redis扩展只允许在1个PHP版本中使用,安装到其它PHP版本请在[软件管理]重装Redis
\
+ - opcache/xcache/apc等脚本缓存扩展,请只安装其中1个,否则可能导致您的站点程序异常
\
+
';
+ $('.soft-man-con').html(con);
+ });
+
+}
+
+//安装扩展
+function installPHPLib(version, name, title, pathinfo) {
+ layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
+ name = name.toLowerCase();
+ var data = "name=" + name + "&version=" + version + "&type=1";
+
+ phpPost('install_lib', version, data, function(data){
+ var rdata = $.parseJSON(data.data);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ getTaskCount();
+ phpLibConfig(version);
+ });
+ });
+}
+
+//卸载扩展
+function uninstallPHPLib(version, name, title, pathinfo) {
+ layer.confirm('您真的要安装{1}吗?'.replace('{1}', name), { icon: 3, closeBtn: 2 }, function() {
+ name = name.toLowerCase();
+ var data = 'name=' + name + '&version=' + version;
+ phpPost('uninstall_lib', version, data, function(data){
+ var rdata = $.parseJSON(data.data);
+ layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
+ getTaskCount();
+ phpLibConfig(version);
+ });
+ });
+}
\ No newline at end of file