supervisor dev 40%

pull/109/head
midoks 3 years ago
parent bde21a5864
commit 149beb8df7
  1. 10
      plugins/supervisor/conf/supervisor.conf
  2. 15
      plugins/supervisor/index.html
  3. 211
      plugins/supervisor/index.py
  4. 12
      plugins/supervisor/install.sh
  5. 198
      plugins/supervisor/js/supervisor.js
  6. 4
      task.py

@ -20,7 +20,7 @@
; is deleted, supervisorctl will be unable to connect to supervisord.
[unix_http_server]
file=/var/run/supervisor.sock
file={$SERVER_PATH}/supervisor/run/supervisor.sock
;chmod=0700 ; socket file mode (default 0700)
;chown=nobody:nogroup ; socket file uid:gid owner
;username=user ; default is no username (open server)
@ -42,11 +42,11 @@ file=/var/run/supervisor.sock
;password=123 ; default is no password (open server)
[supervisord]
logfile=/var/log/supervisor.log
logfile={$SERVER_PATH}/supervisor/log/supervisor.log
logfile_maxbytes=50MB ; max main logfile bytes b4 rotation; default 50MB
logfile_backups=10 ; # of main logfile backups; 0 means none, default 10
loglevel=info ; log level; default info; others: debug,warn,trace
pidfile=/var/run/supervisor.pid
pidfile={$SERVER_PATH}/supervisor/run/supervisor.pid
nodaemon=false ; start in foreground if true; default false
silent=false ; no logs to stdout if true; default false
minfds=1024 ; min. avail startup file descriptors; default 1024
@ -72,7 +72,7 @@ supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
; or inet_http_server section.
[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
serverurl=unix:///{$SERVER_PATH}/supervisor/run/supervisor.sock
;serverurl=http://127.0.0.1:9001 ; use an http:// url to specify an inet socket
;username=chris ; should be same as in [*_http_server] if set
;password=123 ; should be same as in [*_http_server] if set
@ -167,4 +167,4 @@ serverurl=unix:///var/run/supervisor.sock
; include files themselves.
[include]
files = /www/server/supervisor/conf.d/*.ini
files = {$SERVER_PATH}/supervisor/conf.d/*.ini

@ -2,20 +2,25 @@
<div class="bt-w-main">
<div class="bt-w-menu">
<p class="bgw" onclick="pluginService('supervisor');">服务</p>
<p onclick="pluginConfig('supervisor');">进程管理</p>
<p onclick="supList();">进程管理</p>
<p onclick="pluginConfig('supervisor');">配置</p>
<p onclick="pluginConfig('supervisor', '','get_checkdb_pos');">子配置</p>
<p onclick="pluginLogs('supervisor','','get_run_Log', 10);">日志</p>
<p onclick="pluginLogs('supervisor','','run_log', 10);">日志</p>
</div>
<div class="bt-w-con pd15">
<div class="soft-man-con">
</div>
<div class="soft-man-con"></div>
</div>
</div>
</div>
<script type="text/javascript">
<style>
.code{padding: 20px 5px;border: 1px solid #e1e1e1;background: #fcfcfc;border-radius: 4px;line-height: 24px;}
.code span {display: block;margin-left: 15px;margin-bottom: 0;}
</style>
<script type="text/javascript">
resetPluginWinWidth(800);
$.getScript( "/plugins/file?name=supervisor&f=js/supervisor.js", function(){
pluginService('supervisor');
});

@ -4,6 +4,7 @@ import sys
import io
import os
import time
import re
sys.path.append(os.getcwd() + "/class/core")
import mw
@ -41,6 +42,10 @@ def getConfTpl():
return path
def getSubConfDir():
return getServerDir() + "/conf.d"
def getInitDTpl():
path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl"
return path
@ -63,10 +68,17 @@ def getArgs():
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 status():
data = mw.execShell(
"ps -ef|grep supervisor |grep -v grep | awk '{print $2}'")
data = mw.execShell(
"ps -ef|grep supervisor | grep -v grep | grep -v index.py | awk '{print $2}'")
if data[0] == '':
return 'stop'
return 'start'
@ -109,26 +121,35 @@ def start():
return 'ok'
return 'fail'
#| awk '{print $2}'|xargs kill
def stop():
file = initDreplace()
data = mw.execShell(file + ' stop')
initDreplace()
data = mw.execShell('supervisorctl shutdown')
mw.execShell(
"ps -ef|grep supervisor | grep -v grep | grep -v index.py | awk '{print $2}'|xargs kill")
if data[1] == '':
return 'ok'
return 'fail'
def restart():
file = initDreplace()
data = mw.execShell(file + ' restart')
mw.execShell(
"ps -ef|grep supervisor | grep -v grep | grep -v index.py | awk '{print $2}'|xargs kill")
return start()
initDreplace()
data = mw.execShell('supervisorctl reload')
if data[1] == '':
return 'ok'
return 'fail'
def reload():
file = initDreplace()
data = mw.execShell(file + ' reload')
initDreplace()
data = mw.execShell('supervisorctl reload')
if data[1] == '':
return 'ok'
return 'fail'
@ -199,8 +220,168 @@ def initdUinstall():
return 'ok'
def getSupList():
data = {}
statusFile = getServerDir() + "/status.txt"
supCtl = 'supervisorctl'
cmd = "%s update; %s status > %s" % (supCtl, supCtl, statusFile)
mw.execShell(cmd)
with open(statusFile, "r") as fr:
lines = fr.readlines()
array_list = []
process_list = []
for r in lines:
array = r.split()
if array:
d = dict()
program = array[0].split(':')[0]
if program in process_list:
continue
process_list.append(program)
d["program"] = program
d["runStatus"] = array[1]
if array[1] == "RUNNING":
d["status"] = "1"
d["pid"] = array[3][:-1]
else:
d["status"] = "0"
d["pid"] = ""
file = getServerDir() + '/conf.d/' + program + ".ini"
if not os.path.exists(file):
continue
with open(file, "r") as fr:
infos = fr.readlines()
for line in infos:
if "command=" in line.strip():
d["command"] = line.strip().split('=')[1]
if "user=" in line.strip():
d["user"] = line.strip().split('=')[1]
if "priority=" in line.strip():
d["priority"] = line.strip().split('=')[1]
if "numprocs=" in line.strip():
d["numprocs"] = line.strip().split('=')[1]
array_list.append(d)
# print(array_list)
data = {}
data['data'] = array_list
return mw.getJson(data)
def getUserList():
user = getServerDir() + "/user.txt"
if not os.path.isfile(user):
os.system(r"touch {}".format(user))
res = mw.execShell("cat /etc/passwd > " + user)
with open(user, "r") as fr:
users = fr.readlines()
fr.close()
os.remove(user)
user_list = []
special = ["bin", "daemon", "adm", "lp", "shutdown", "halt", "mail", "operator", "games",
"avahi-autoipd", "systemd-bus-proxy", "systemd-network", "dbus", "polkitd", "tss", "ntp"]
for u in users:
user = re.split(':', u)[0]
if user[0] == '#':
continue
if user in special:
continue
user_list.append(user)
return mw.getJson(user_list)
def addJob():
args = getArgs()
data = checkArgs(args, ['name', 'user', 'path', 'command', 'numprocs'])
if not data[0]:
return data[1]
program = args['name']
command = args['command']
path = args['path']
numprocs = args['numprocs']
user = args['user']
log_dir = getServerDir() + '/log/'
w_body = ""
w_body += "[program:" + program + "]" + "\n"
w_body += "command=" + command + "\n"
w_body += "directory=" + path + "\n"
w_body += "autorestart=true" + "\n"
w_body += "startsecs=3" + "\n"
w_body += "startretries=3" + "\n"
w_body += "stdout_logfile=" + log_dir + program + ".out.log" + "\n"
w_body += "stderr_logfile=" + log_dir + program + ".err.log" + "\n"
w_body += "stdout_logfile_maxbytes=2MB" + "\n"
w_body += "stderr_logfile_maxbytes=2MB" + "\n"
w_body += "user=" + user + "\n"
w_body += "priority=999" + "\n"
w_body += "numprocs={0}".format(numprocs) + "\n"
w_body += "process_name=%(program_name)s_%(process_num)02d"
dstFile = getSubConfDir() + "/" + program + '.ini'
mw.writeFile(dstFile, w_body)
return mw.returnJson(True, '增加守护进程成功!')
def delJob():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
supCtl = 'supervisorctl'
log_dir = getServerDir() + '/log/'
result = mw.execShell("{0} stop ".format(supCtl) + name)
program = getServerDir() + "/conf.d/" + name + ".ini"
# 删除日志文件
outlog = log_dir + name + ".out.log"
if os.path.isfile(outlog):
os.remove(outlog)
errlog = log_dir + name + ".err.log"
if os.path.isfile(errlog):
os.remove(errlog)
# 删除ini文件
if os.path.isfile(program):
os.remove(program)
result = mw.execShell(
"{0} update".format(supCtl))
return mw.returnJson(True, '删除守护进程成功!')
else:
result = mw.execShell(
"{0} update".format(supCtl))
return mw.returnJson(False, '该守护进程不存在!')
def updateJob():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
def getJobInfo():
args = getArgs()
data = checkArgs(args, ['name'])
if not data[0]:
return data[1]
name = args['name']
def runLog():
return getServerDir() + '/data/redis.log'
return getServerDir() + '/log/supervisor.log'
if __name__ == "__main__":
func = sys.argv[1]
@ -226,5 +407,17 @@ if __name__ == "__main__":
print(getConf())
elif func == 'run_log':
print(runLog())
elif func == 'get_user_list':
print(getUserList())
elif func == 'get_sup_list':
print(getSupList())
elif func == 'add_job':
print(addJob())
elif func == 'del_job':
print(delJob())
elif func == 'update_job':
print(updateJob())
elif func == 'get_job_info':
print(getJobInfo())
else:
print('error')

@ -35,16 +35,22 @@ Install_app()
echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source
mkdir -p $serverPath/supervisor
mkdir -p $serverPath/supervisor/log
mkdir -p $serverPath/supervisor/run
echo 'supervisor install...'
if [ "centos" == "$OSNAME" ] || [ "fedora" == "$OSNAME" ];then
yum install supervisor -y
# yum install supervisor -y
pip install supervisor
elif [ "ubuntu" == "$OSNAME" ] || [ "debian" == "$OSNAME" ] ;then
apt install supervisor -y
# apt install supervisor -y
pip install supervisor
else
brew install supervisor
pip install supervisor
# brew install supervisor
fi
echo "${VERSION}" > $serverPath/supervisor/version.pl
echo '安装完成' > $install_tmp
}

@ -1,5 +1,4 @@
function myPost(method,args,callback, title){
var _args = null;
@ -27,3 +26,200 @@ function myPost(method,args,callback, title){
}
},'json');
}
function supList(page, search){
var _data = {};
if (typeof(page) =='undefined'){
var page = 1;
}
_data['page'] = page;
_data['page_size'] = 10;
if(typeof(search) != 'undefined'){
_data['search'] = search;
}
myPost('get_sup_list', _data, function(data){
var rdata = $.parseJSON(data.data);
console.log(rdata.data);
var list = '';
for(i in rdata.data){
list += '<tr>';
list += '<td>' + rdata.data[i]['program'] +'</td>';
list += '<td>' + rdata.data[i]['command'] +'</td>';
list += '<td>' + rdata.data[i]['user'] +'</td>';
list += '<td>' + rdata.data[i]['pid'] +'</td>';
list += '<td>' + rdata.data[i]['numprocs'] +'</td>';
list += '<td>' + rdata.data[i]['priority'] +'</td>';
list += '<td>' + rdata.data[i]['runStatus'] +'</td>';
list += '<td>' + rdata.data[i]['runStatus'] +'</td>';
list += '<td style="text-align:right">\
<a href="javascript:;" class="btlink" onclick="openPhpmyadmin(\''+rdata.data[i]['name']+'\',\''+rdata.data[i]['username']+'\',\''+rdata.data[i]['password']+'\')" title="启动|停止">启动</a> | ' +
'<a href="javascript:;" class="btlink" onclick="setDbPass('+rdata.data[i]['id']+',\''+ rdata.data[i]['username'] +'\',\'' + rdata.data[i]['password'] + '\')">改密</a> | ' +
'<a href="javascript:;" class="btlink" onclick="delJob(\''+rdata.data[i]['program']+'\')" title="删除">删除</a>' +
'</td>';
list += '</tr>';
}
if(rdata.data.length==0){
list = "<tr><td colspan='9'>当前没有数据</td></tr>";
}
var con = '<div class="safe bgw">\
<button onclick="supAdd()" title="添加守护进程" class="btn btn-success btn-sm" type="button" style="margin-right: 5px;">添加守护进程</button>\
<div class="divtable mtb10">\
<div class="tablescroll">\
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
<thead>\
<th>名称</th>\
<th>启动命令</th>\
<th>启动用户</th>\
<th>进程ID</th>\
<th>进程数量</th>\
<th>优先级</th>\
<th>进程管理</th>\
<th>状态</th>\
<th style="text-align:right;">操作</th></tr></thead>\
<tbody>\
'+ list +'\
</tbody></table>\
</div>\
<div id="databasePage" class="dataTables_paginate paging_bootstrap page"></div>\
</div>\
</div>';
con += '<div class="code">\
<span>supervisord 常见进程状态详细如下</span>\
<span>1STOPPED该进程已停止 2STOPPING由于停止请求该进程正在停止</span>\
<span>3RUNNING该进程正在运行 4STARTING该进程由于启动请求而开始</span>\
<span>5FATAL该进程无法成功启动</span>\
<span>6BACKOFF该进程进入 启动状态但随后退出的速度太快而无法移至 运行状态</span>\
</div>'
$(".soft-man-con").html(con);
$('#databasePage').html(rdata.page);
});
}
//卸载软件
function delJob(name) {
layer.confirm(msgTpl('是否删除守护进程[{1}]?', [name]), { icon: 3, closeBtn: 2 }, function() {
///////////////////////////////////////
var data = {'name': name};
var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] });
myPost('del_job', data, function(rdata){
layer.close(loadT)
rdata = $.parseJSON(rdata.data);
supList(1,10);
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
});
///////////////////////////////////////
});
}
//添加站点
function supAdd() {
myPost('get_user_list',{},function(data){
var rdata = $.parseJSON(data.data);
// console.log(rdata);
var defaultPath = $("#defaultPath").html();
var ulist = "<div class='line'><span class='tname'>启动用户</span><select class='bt-input-text' name='user' id='c_k3' style='width:270px'>";
for (var i=rdata.length-1;i>=0;i--) {
ulist += "<option value='"+rdata[i]+"'>"+rdata[i]+"</option>";
}
var www = syncPost('/site/get_root_dir');
ulist += "</select><span id='php_w' style='color:red;margin-left: 10px;width:270px;'></span></div>";
layer.open({
type: 1,
area: '500px',
title: '添加守护进程',
closeBtn: 2,
shift: 0,
shadeClose: false,
btn: ['确定', '取消'],
content: "<div class='bt_conter bt-form pd15' style='height:auto;width:100%;'>\
<div class='line'>\
<span class='tname'>名称</span>\
<div class='info-r c4'>\
<input id='name' class='bt-input-text' type='text' name='name' placeholder='请输入名称' style='width:270px' />\
</div>\
</div>\
"+ulist+"\
<div class='line'>\
<span class='tname'>运行目录</span>\
<div class='info-r c4'>\
<input id='inputPath' class='bt-input-text mr5' type='text' name='path' placeholder='请选择运行目录' value='"+www['dir']+"/' placeholder='"+www['dir']+"' style='width:270px' />\
<span class='glyphicon glyphicon-folder-open cursor' onclick='changePath(\"inputPath\")'></span>\
</div>\
</div>\
<div class='line'>\
<span class='tname'>启动命令</span>\
<div class='info-r c4'>\
<input id='command' class='bt-input-text' type='text' name='command' placeholder='请输入启动命令' style='width:270px' />\
</div>\
</div>\
<div class='line'>\
<span class='tname'>进程数量</span>\
<div class='info-r c4'>\
<input id='numprocs' class='bt-input-text' type='text' name='numprocs' value='1' style='width:270px' />\
</div>\
</div>\
<ul class='help-info-text c7' style='padding-left: 29px;margin-top:5px;'>\
<li style='color:#F00'>注意填写进程名称请使用英文暂不支持中文</li>\
<li>如果启动命令里面有文件请填写文件的绝对路径</li>\
<li>进程数量默认值为1如果值为大于1的整数则相当于多进程</li>\
</ul>\
</div>",
yes: function(index, layero){
// console.log(index,layero);
var options = ['name','user','path','command','numprocs'];
var opval = {};
for(var i in options){
opval[options[i]] = $('[name="'+ options[i] +'"]').val();
if(opval[options[i]] == ''){
if(options[i] == 'name'){
layer.msg('进程名称不能为空');
return false;
}else if(options[i] == 'user'){
layer.msg('启动用户不能为空');
return false;
}else if(options[i] == 'path'){
layer.msg('运行目录不能为空');
return false;
}else if(options[i] == 'command'){
layer.msg('启动命令不能为空');
return false;
}else if(options[i] == 'numprocs'){
layer.msg('进程数量不能为空!');
return false;
}
}
}
var numprocs = $('[name=numprocs]').val();
if (!(/(^[1-9]\d*$)/.test(numprocs))) {
layer.msg('进程数量请输入正整数')
return false;
  }
myPost("add_job", opval, function(data){
rdata = $.parseJSON(data.data);
layer.msg(rdata.msg,{icon:rdata.status?1:2});
rdata.status ? layer.close(index):'';
supList(1,10);
})
return;
}
});
});
}

@ -185,9 +185,9 @@ def mainSafe():
return True
isCheck = 0
isStart = mw.execShell(
"ps aux |grep 'python main.py'|grep -v grep|awk '{print $2}'")[0]
"ps aux |grep 'python3 main.py'|grep -v grep|awk '{print $2}'")[0]
if not isStart:
os.system('/etc/init.d/bt start')
os.system('/etc/init.d/mw start')
isStart = mw.execShell(
"ps aux |grep 'python main.py'|grep -v grep|awk '{print $2}'")[0]
mw.writeLog('守护程序', '面板服务程序启动成功 -> PID: ' + isStart)

Loading…
Cancel
Save