Files
yakpanel-core/mod/project/java/projectMod.py
2026-04-07 02:04:22 +05:30

3252 lines
131 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import itertools
import json
import re
import shutil
import sys
import os
import time
import traceback
import threading
from datetime import datetime
import psutil
from typing import Dict, List, Optional, Union, Any
from mod.base import json_response
from mod.base.backup_tool import VersionTool
from mod.project.java import utils
from mod.base.process import RealUser, RealProcess
if "/www/server/panel/class" not in sys.path:
sys.path.insert(0, "/www/server/panel/class")
import public
from projectModel.watchModel import use_project_watch, add_project_watch, del_project_watch
from mod.base.web_conf import normalize_domain, is_domain, Redirect, remove_sites_service_config, RealSSLManger
from mod.base.web_conf import RealRedirect, RealLogMgr, Proxy, RealProxy
from mod.base.process.server import RealServer
from mod.project.java.java_web_conf import JvavWebConfig
from mod.project.java.server_proxy import RealServerProxy
from mod.base.git_tool import GitMager
from mod.project.java.springboot_parser import SpringConfigParser, SpringLogConfigParser
_DEBUG = True
def debug(func):
if not _DEBUG:
return func
def inner(*args, **kwargs):
try:
return func(*args, **kwargs)
except:
err = traceback.format_exc()
print(err)
public.print_log(err)
return {"msg": "报错了"}
return inner
def set_java_service_link():
java_service_bin = '/usr/bin/java-service'
java_service_src = '/www/server/panel/script/java-service.py'
if os.path.exists(java_service_src):
public.ExecShell("chmod 700 " + java_service_src)
if not os.path.exists(java_service_bin):
if os.path.exists(java_service_src):
public.ExecShell("ln -sf {} {}".format(java_service_src, java_service_bin))
set_java_service_link()
class main(JvavWebConfig, Proxy, Redirect, GitMager):
def __init__(self):
super().__init__()
self._bt_tomcat_path = "/usr/local/bttomcat"
self._mod_tomcat_path = "/usr/local/bt_mod_tomcat"
self._bt_jdk_path = "/usr/local/btjdk/"
self._java_path = "/www/server/java/"
self._vhost_path = "/www/server/panel/vhost"
self._java_project_path = "/var/tmp/springboot/"
self._java_project_vhost = "/var/tmp/springboot/vhost"
self._java_spring_boot_log_path = "/www/wwwlogs/java/springboot"
self._site_tomcat_path = '/www/server/bt_tomcat_web/'
if not os.path.exists(self._java_project_vhost):
os.makedirs(self._java_project_vhost + "/pids", 0o777)
os.makedirs(self._java_project_vhost + "/scripts", 0o755)
if not os.path.exists(self._java_project_vhost + "/env"):
os.makedirs(self._java_project_vhost + "/env", 0o755)
if not os.path.exists(self._java_spring_boot_log_path):
os.makedirs(self._java_spring_boot_log_path, 0o755)
if not os.path.exists(self._site_tomcat_path):
os.makedirs(self._site_tomcat_path, 0o755)
if not os.path.exists(self._mod_tomcat_path):
os.makedirs(self._mod_tomcat_path, 0o755)
self._default_java_log = "/www/wwwlogs/java"
if not os.path.exists(self._default_java_log):
os.makedirs(self._default_java_log, 0o701)
# 实现Proxy初始化
Proxy.__init__(self, config_prefix="java_")
# 实现Redirect初始化
Redirect.__init__(self, config_prefix="java_")
self._real_process: Optional[RealProcess] = None
@property
def real_process(self) -> RealProcess:
if self._real_process is None:
self._real_process = RealProcess()
return self._real_process
@staticmethod
def is_stop_by_user(project_id):
return utils.is_stop_by_user(project_id)
@staticmethod
def write_project_log(log_str: str):
public.WriteLog("项目管理", log_str)
def get_system_info(self, get=None):
return json_response(status=True, data={
"jdk_info": self._local_jdk_info(),
"tomcat_status": self._bt_tomcat_info(),
})
@staticmethod
def _local_jdk_info() -> List[Dict]:
ret = []
jdk_tool = utils.JDKManager()
current_java_home = jdk_tool.get_env_jdk()
# 获取已安装的JDK版本
for version in jdk_tool.versions_list:
jdk_path = '/www/server/java/' + version + '/bin/java'
is_current = os.path.dirname(os.path.dirname(jdk_path)) == current_java_home
if os.path.exists('/www/server/java/' + version):
ret.append({'name': version, 'path': jdk_path, 'operation': 1, 'is_current': is_current})
else:
ret.append({'name': version, 'path': '', 'operation': 0, 'is_current': False})
name = '安装[{}]'.format(version)
install_data = public.M('tasks').where("status in (0, -1) and name=?", (name,)).find()
if install_data:
ret[-1]['operation'] = 3
ret.sort(key=lambda x: (x['operation'] == 1, x['operation'] == 3), reverse=True)
# 检查其他JDK路径
jdk_paths = [
('JDK', '/usr/bin/java'),
('jdk8', '/usr/java/jdk1.8.0_121/bin/java'),
('openjdk8', '/usr/local/btjdk/jdk8/bin/java'),
('jdk7', '/usr/java/jdk1.7.0_80/bin/java')
]
for i in jdk_tool.custom_jdk_list:
is_current = utils.normalize_jdk_path(i) == current_java_home
ret.append({'name': '自定义JDK', 'path': i, 'operation': 1, 'is_current': is_current})
for name, path in jdk_paths:
if os.path.exists(path):
is_current = os.path.dirname(os.path.dirname(path)) == current_java_home
ret.append({'name': name, 'path': path, 'operation': 2, 'is_current': is_current})
return ret
@staticmethod
def _bt_tomcat_info() -> List[Dict]:
versions = [7, 8, 9, 10]
data = []
for i in versions:
soft_name = "安装[Java项目Tomcat-{}]".format(i)
install_data = public.M('tasks').where("status in (0, -1) and name=?", (soft_name,)).find()
tmp = utils.bt_tomcat(i).status()
tmp["version"] = i
if install_data:
tmp["is_install"] = True
else:
tmp["is_install"] = False
data.append(tmp)
return data
@staticmethod
def process_for_create(get):
is_java_process = True
search = ''
if hasattr(get, "is_java_process"):
is_java_process = get.is_java_process.strip()
if is_java_process in ("0", 0, False, "false"):
is_java_process = False
else:
is_java_process = True
if hasattr(get, "search"):
search = get.search.strip()
res = []
rep_bt_tomcat = re.compile(r"(/usr/local/bttomcat/.*)|(/www/server/bt_tomcat_web/.*)/jsvc")
rep_not_use = re.compile(
r"php|system|crond|NetworkManager|uwsgi|dotnet|bash|/www/server/tamper|mysql|nginx|httpd|tail|python|sshd"
)
if is_java_process:
target_list = utils.jps()
for pid in target_list:
try:
p = psutil.Process(pid)
if search and not (search in p.name() or search in ' '.join(p.cmdline())): # 有搜索条件,但不符合搜索条件
continue
if rep_bt_tomcat.search(p.exe()):
continue
res.append({
"pid": pid,
"name": p.name(),
"exe": p.exe(),
"cmdline": p.cmdline(),
"username": p.username(),
"create_time:": p.create_time(),
"status": p.status(),
})
except:
continue
return res
# 若未选择java进程 则在所有进程中搜索
for i in psutil.process_iter(["pid", "name", "exe", "cmdline", "username", "create_time", "status"]):
if not i.exe():
continue
if rep_not_use.search(i.exe()):
continue
if search and not (search in i.name() or search in ' '.join(i.cmdline())): # 有搜索条件, 但不符合搜索条件
continue
if rep_bt_tomcat.search(i.exe()):
continue
try:
res.append({
"pid": i.pid,
"name": i.name(),
"exe": i.exe(),
"cmdline": i.cmdline(),
"username": i.username(),
"create_time:": i.create_time(),
"status": i.status(),
})
except:
continue
return res
@staticmethod
def process_info_for_create(get):
try:
pid = int(get.pid.strip())
except:
return json_response(status=False, msg="Parameter error")
try:
p = psutil.Process(pid)
cmdline = p.cmdline()
ports = []
for i in p.connections():
if i.status == "LISTEN" and i.laddr and i.laddr.port not in ports:
ports.append(i.laddr.port)
user = p.username()
env = p.environ()
exe = p.exe()
except:
public.print_log(public.get_error_info())
return json_response(status=False, msg="进程解析失败")
pwd_path = env.get("PWD")
env_list = []
for key, value in env.items():
if key.lower().find("spring") != -1 or key.lower().find("java") != -1:
env_list.append({"k": key, "v": value})
java_bin = ""
if exe.endswith("java"): # 目前支持用户使用java命令启动的java进程
java_bin = exe
if cmdline[0].endswith("java"):
cmdline[0] = java_bin
jar_path = ""
target_jar_idx = None
for idx, i in enumerate(cmdline):
if i.endswith(".jar") or i.endswith(".war") and not (i.startswith("-") or "=" in i):
if not jar_path:
jar_path = i
target_jar_idx = idx
# 处理获取的java路径
project_name = ""
if jar_path:
if not jar_path.startswith("/"): # 处理相对路径
jar_path = os.path.abspath(os.path.join(pwd_path, jar_path))
cmdline[target_jar_idx] = jar_path
project_name = os.path.basename(jar_path).rsplit(".", 1)[0]
if not os.path.exists(jar_path):
jar_path = None
return json_response(status=True, data={
"project_name": project_name,
"jar_path": jar_path,
"java_bin": java_bin,
"port": ports[0] if len(ports) else 0,
"user": user,
"env": env_list,
"cmdline": " ".join(cmdline),
"pid": pid,
})
@staticmethod
def check_spring_boot_args(get) -> Union[Dict, str]:
by_process = 0
domains = []
proxy_path = "/"
jmx_status = False
watch_file = False
env_file = ""
env_list = []
try:
project_name = get.project_name.strip()
project_jar = get.project_jar.strip()
project_jdk = get.project_jdk.strip()
# port = int(get.port)
run_user = get.run_user.strip()
project_cmd = get.project_cmd.strip() # type:str
ps = get.project_ps.strip()
if hasattr(get, "env_file"):
env_file = get.env_file.strip()
if not isinstance(env_file, str) and os.path.exists(env_file):
return "环境变量文件不存在"
if hasattr(get, "env_list"):
env_list = get.env_list
if not isinstance(env_list, list):
return "环境变量格式错误"
if hasattr(get, "domains"):
domains = get.domains
if not isinstance(domains, list):
return "域名参数错误"
if hasattr(get, "proxy_path"):
proxy_path = get.proxy_path
if not isinstance(domains, str) and not proxy_path.startswith("/"):
return "代理路径必须是以/开头的字符串"
if hasattr(get, "jmx_status"):
jmx_status = utils.js_value_to_bool(get.jmx_status)
if hasattr(get, "watch_file"):
watch_file = utils.js_value_to_bool(get.watch_file)
if hasattr(get, "by_process"):
by_process = int(get.by_process)
if by_process < 0:
by_process = 0
except (AttributeError, ValueError):
return "Parameter format error"
if not project_name:
return "The project name cannot be empty"
if not 1 <= len(project_name) <= 20:
return "项目名称不超过20字符"
if public.M('sites').where('name=?', (project_name,)).count():
return '指定项目名称已存在: {}'.format(project_name)
if not os.path.exists(project_jar):
return '请输入正确的jar包路径'
project_jdk = utils.normalize_jdk_path(project_jdk)
if not isinstance(project_jdk, str):
return json_response(False, '项目JDK路径不存在')
if not os.path.exists(project_jdk):
return '请输入正确的JDK路径'
if not utils.test_jdk(project_jdk):
return '请输入正确的JDK路径'
if project_cmd.find(project_jdk) == -1:
return '启动命令中不包含JDK路径请确认无误再添加'
if project_cmd.find(project_jar) == -1:
return '启动命令中不包含jar路径请确认无误后再添加'
# if not by_process and not utils.check_port(port):
# return '端口格式错误或已被其他进程使用'
if domains:
if not public.is_apache_nginx():
return "未安装Nginx"
err_msg = public.checkWebConfig()
if isinstance(err_msg, str):
return (
'WEB服务器配置配置文件错误ERROR:<br><font style="color:red;">'
+ err_msg.replace("\n", '<br>') + '</font>'
)
if run_user not in [i["username"] for i in RealUser().get_user_list()["data"]]:
return '请输入正确的启动用户'
if domains:
domains, err = normalize_domain(*domains)
if err:
return "<br>".join(["域名:{},错误信息:{}".format(i['domain'], i['msg']) for i in err])
else:
for d, p in domains:
if public.M('domain').where('name=?', d).count():
return '指定域名已存在: {}'.format(d)
return {
"project_name": project_name,
"project_jar": project_jar,
"project_jdk": project_jdk,
# "port": port,
"run_user": run_user,
"project_cmd": project_cmd,
"ps": ps,
"env_list": env_list,
"env_file": env_file,
"domains": ["{}:{}".format(i[0], i[1]) for i in domains],
"proxy_path": proxy_path,
"jmx_status": jmx_status,
"watch_file": watch_file,
"by_process": by_process,
}
def create_spring_boot_project(self, get):
config = self.check_spring_boot_args(get)
if isinstance(config, str):
return json_response(status=False, msg=config)
project_config = {
'ssl_path': '/www/wwwroot/java_node_ssl',
'project_jdk': config["project_jdk"],
'project_name': config["project_name"],
'project_jar': config["project_jar"],
'bind_extranet': 0 if not config["domains"] else 1,
'domains': config["domains"],
'run_user': get.run_user.strip(),
'jmx_status': config["jmx_status"],
'project_cmd': config["project_cmd"],
'java_type': 'springboot',
'jar_path': os.path.dirname(config["project_jar"]),
'pids': "{}/pids/{}.pid".format(self._java_project_vhost, config["project_name"]),
'logs': "{}/{}.log".format(self._java_spring_boot_log_path, config["project_name"]),
'scripts': "{}/scripts/{}.sh".format(self._java_project_vhost, config["project_name"]),
'watch_file': config["watch_file"],
'env_list': config["env_list"],
'env_file': config["env_file"],
'proxy_path': config["proxy_path"],
"nohup_log": True,
"static_info": {},
"proxy_info": [],
"daemon_status": False,
"server_name_suffix": ""
}
pdata = {
'name': config["project_name"],
'path': config["project_jar"],
'ps': config["ps"],
'status': 1,
'type_id': 0,
'project_type': 'Java',
'project_config': json.dumps(project_config),
'addtime': public.getDate()
}
project_id = public.M('sites').insert(pdata)
if not isinstance(project_id, int):
return json_response(status=False, msg='创建项目失败')
pdata["project_config"] = project_config
pdata["id"] = project_id
if project_config["domains"]:
for domain in project_config["domains"]:
domain_name, port = domain.split(":")
public.M('domain').insert(
{
'name': domain_name,
'pid': project_id,
'port': port,
'addtime': public.getDate()
}
)
error_msg = self._setup_spring_boot_project(pdata, by_process=config["by_process"])
if error_msg:
return json_response(status=True, msg=error_msg)
return json_response(status=True, msg='项目创建成功, 若未能启动成功, 请查看日志信息,获取启动失败原因')
def _setup_spring_boot_project(self, pdata, by_process=False) -> Optional[str]:
project_config = pdata["project_config"]
if project_config["jmx_status"]:
pass
# project_config["project_cmd"] = self._build_jmx_cmd(project_config["project_cmd"], project_config['jmx_status'])
if not by_process:
start_status = self._start_spring_boot_project(pdata, write_systemd_file=True, need_wait=False)
if isinstance(start_status, dict):
start_status = start_status["msg"]
else:
public.writeFile(project_config['pids'], str(by_process))
start_status = "Successfully added"
if project_config["watch_file"]:
add_project_watch(
p_name=project_config["project_name"],
p_type="java",
site_id=pdata["id"],
watch_path=project_config["project_jar"]
)
if project_config["domains"]:
res = self.create_config(
pdata,
domains=[i.split(":", 1) for i in project_config["domains"]],
use_ssl=False,
)
return start_status
# 实际启动项目的函数
def _start_spring_boot_project(self,
project_data: dict,
write_systemd_file=True,
need_wait=True,
) -> dict:
old_pid = self.get_project_pid(project_data)
project_config = project_data["project_config"]
server_name = "spring_" + project_config["project_name"] + project_config.get("server_name_suffix", "")
# 先检查环境变量文件是否存在,没有的时候先写空
env_file = project_config['env_file']
env_list = project_config['env_list']
env_path = "{}/env/{}.env".format(self._java_project_vhost, project_config["project_name"])
if isinstance(env_list, list):
if not os.path.exists(os.path.dirname(env_path)):
os.makedirs(os.path.dirname(env_path), 0o755)
public.writeFile(env_path, "\n".join(
["{}={}".format(i["k"], i["v"]) for i in env_list if "k" in i and "v" in i]
))
else:
if not os.path.isfile(env_path):
public.writeFile(env_path, "")
if env_file and not os.path.isfile(env_file):
if not os.path.exists(os.path.dirname(env_file)):
os.makedirs(os.path.dirname(env_file), 0o755)
public.writeFile(env_file, "")
log_file = project_config['logs']
pid_file = project_config['pids']
if not os.path.exists(log_file):
public.writeFile(log_file, "")
if not os.path.exists(pid_file):
public.writeFile(pid_file, "0")
# 修改文件权限
public.ExecShell(
"chown {usr}:{usr} {file}".format(usr=project_config["run_user"], file=project_config["project_jar"])
)
public.ExecShell(
"chown {usr}:{usr} {file}".format(usr=project_config["run_user"], file=log_file)
)
public.ExecShell(
"chown {usr}:{usr} {file}".format(usr=project_config["run_user"], file=pid_file)
)
utils.pass_dir_for_user(os.path.dirname(log_file), project_config['run_user'])
# 如果存在服务文件,没有要求写入时,就直接执行启动停止操作
s_admin = RealServer()
if not write_systemd_file:
res = s_admin.daemon_status(server_name)
msg = res['msg']
if msg in ("运行中", "未运行"):
s_admin.daemon_admin(server_name, "restart")
if need_wait:
return self._wait_start_status(project_data, old_pid=old_pid)
else:
return json_response(status=True, msg="操作已执行")
if msg == "operation failure":
return res
# 还有一种服务文件丢失的情况走下面的写文件并启动
# 要求写入时, 重新写入启动文件
project_cmd = project_config['project_cmd']
# 前置准备
if project_config["nohup_log"]:
collect_log = log_file
else:
collect_log = '/dev/null'
jar_path = project_config['jar_path']
env = "EnvironmentFile={}".format(env_path)
if env_file:
env += "\nEnvironmentFile={}".format(env_file)
res = s_admin.create_daemon(
server_name=server_name,
pid_file=pid_file,
start_exec=project_cmd,
workingdirectory=jar_path,
user=project_config["run_user"],
logs_file=collect_log,
environments=env,
restart_type="always" if project_config.get("daemon_status", False) else "no"
)
if not res["status"]:
return res
s_admin.daemon_admin(server_name, "start")
if need_wait:
return self._wait_start_status(project_data, old_pid=old_pid)
return json_response(status=True, msg="操作已执行")
def _wait_start_status(self, project_data: dict, old_pid: int) -> dict:
# 当为重启时,等待关闭
if old_pid:
try:
p = psutil.Process(old_pid)
for i in range(20):
time.sleep(0.05)
if not p.is_running():
break
except:
pass
project_config = project_data['project_config']
pid = self.get_project_pid(project_data)
if not pid:
for i in range(2):
time.sleep(0.05)
pid = self.get_project_pid(project_data)
if pid:
break
if not pid:
return json_response(False,
msg="启动失败,详细信息请查看日志",
data=public.GetNumLines(project_config["logs"], 30))
for i in range(3):
port = self._get_port_by_pid(pid)
if port:
return json_response(True, "启动成功")
time.sleep(0.05)
if i > 1 and i % 5 == 0:
if pid not in psutil.pids():
return json_response(False,
msg="启动失败,详细信息请查看日志",
data=public.GetNumLines(project_config["logs"], 30))
pid = self.get_project_pid(project_data)
if not pid:
return json_response(False,
msg="启动失败,详细信息请查看日志",
data=public.GetNumLines(project_config["logs"], 30))
else:
return json_response(True, "未检查到端口监听,启动过程超时,请注意启动情况")
@staticmethod
def _get_port_by_pid(pid: int) -> Optional[int]:
try:
p = psutil.Process(pid)
for i in p.connections():
if i.status == "LISTEN":
return i.laddr.port
except:
return None
# # 启动脚本
# start_cmd = '''#!/bin/bash
# PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
# export PATH
# {env}
# cd {jar_path}
# nohup {project_cmd} {collect_log} &
# echo $! > {pid_file}
# '''.format(
# jar_path=jar_path,
# project_cmd=project_cmd,
# pid_file=pid_file,
# log_file=log_file,
# env=env,
# collect_log=collect_log
# )
# script_file = project_config['scripts']
# # 写入启动脚本
# public.writeFile(script_file, start_cmd)
# if os.path.exists(pid_file):
# os.remove(pid_file)
# public.set_mode(script_file, 755)
# # 修改文件权限
# public.ExecShell(
# "chown {usr}:{usr} {file}".format(usr=project_config["run_user"], file=project_config["project_jar"])
# )
# if not os.path.exists(log_file):
# public.writeFile(log_file, "")
#
# public.ExecShell(
# "chown {usr}:{usr} {file}".format(usr=project_config["run_user"], file=log_file)
# )
# utils.pass_dir_for_user(os.path.dirname(log_file), project_config['run_user'])
# # 执行脚本文件
# res = public.ExecShell("bash {}".format(script_file), user=project_config['run_user'], env=os.environ.copy())
#
# time.sleep(1)
# error_msg = '启动失败,您可以尝试查看控制台日志,以获取具体失败原因'
# if not os.path.exists(pid_file):
# return error_msg
#
# # 获取PID
# try:
# pid = int(public.readFile(pid_file))
# except:
# return error_msg
# if pid not in psutil.pids():
# return error_msg
#
# return None
@staticmethod
def _build_jmx_cmd(cmd_str: str, jmx_status: bool):
has_jmx_args = cmd_str.find("-Dcom.sun.management.jmxremote") != -1
if not jmx_status:
if not has_jmx_args:
return cmd_str
cmd_str_list = cmd_str.split(" ")
for i in range(len(cmd_str_list) - 1, -1, -1):
if cmd_str_list[i].startswith("-Dcom.sun.management.jmxremote"):
cmd_str_list.pop(i)
if cmd_str_list[i].startswith("-Djava.rmi.server.hostname=127.0.0.1"):
cmd_str_list.pop(i)
return " ".join(cmd_str_list)
if jmx_status and has_jmx_args:
port = re.search(r"-Dcom\.sun\.management\.jmxremote\.port=(?P<port>\d+)", cmd_str)
if not utils.check_port(port.group("port")): # 如果原来的port被占用了则生成一个随机的port并替换
cmd_str = re.sub(
r"-Dcom\.sun\.management\.jmxremote\.port=(\d+)",
"-Dcom.sun.management.jmxremote.port={}".format(utils.create_a_not_used_port()),
cmd_str
)
return cmd_str
add_cmd = (
" -Dcom.sun.management.jmxremote"
" -Dcom.sun.management.jmxremote.port={}"
" -Djava.rmi.server.hostname=127.0.0.1"
" -Dcom.sun.management.jmxremote.local.only=true"
" -Dcom.sun.management.jmxremote.authenticate=false"
" -Dcom.sun.management.jmxremote.ssl=false"
).format(utils.create_a_not_used_port())
cmd_str = cmd_str.lstrip(" ")
first_space_idx = cmd_str.find(" ") # 把jmx的配置放到第一个空格之后
if first_space_idx == -1:
return cmd_str + add_cmd
else:
return cmd_str[:first_space_idx] + add_cmd + cmd_str[first_space_idx:]
@staticmethod
def check_tomcat_args(get) -> Union[Dict, str]:
port = None
jdk_path = None
try:
domain = get.domain.strip()
tomcat_version = int(get.tomcat_version)
project_path = get.project_path.strip()
if hasattr(get, "port"):
port = int(get.port)
if hasattr(get, "jdk_path"):
jdk_path = get.jdk_path.strip()
ps = get.project_ps.strip()
except:
return "Parameter error"
if not is_domain(domain):
return "请输入正确的域名"
if not os.path.exists(project_path):
os.makedirs(project_path)
public.set_own(project_path, 'www')
if tomcat_version not in (7, 8, 9, 10):
return "请选择正确的Tomcat版本"
if jdk_path is not None:
if not os.path.exists(jdk_path):
return "JDK路径不存在"
jdk_path = utils.normalize_jdk_path(jdk_path)
if not isinstance(jdk_path, str):
return '项目JDK路径不存在'
if not utils.test_jdk(jdk_path):
return "JDK路径错误"
if port is not None:
if not utils.check_port(port):
return "端口被占用"
domain_list, err = normalize_domain(domain)
if not err:
domain = domain_list[0]
if public.M('domain').where('name=?', domain[0]).count():
return '指定域名已存在: {}'.format(domain[0])
project_name = domain[0]
domain = "{}:{}".format(domain[0], domain[1])
else:
return "<br>".join(["域名:{},错误信息:{}".format(i['domain'], i['msg']) for i in err])
return {
"project_name": project_name,
"project_jdk": jdk_path,
"ps": ps,
"port": port,
"domains": [domain, ],
"tomcat_version": tomcat_version,
"project_path": project_path,
}
def create_tomcat_project(self, get):
config = self.check_tomcat_args(get)
if isinstance(config, str):
return json_response(status=False, msg=config)
tomcat = utils.bt_tomcat(config["tomcat_version"])
if not tomcat.installed:
return json_response(status=False, msg="指定的Tomcat版本未安装")
if config["project_jdk"] and tomcat.jdk_path != config["project_jdk"]:
if not tomcat.replace_jdk(config["project_jdk"]):
return json_response(status=False, msg="替换JDK失败")
if config["port"] and not tomcat.set_port(config["port"]):
return json_response(status=False, msg="设置端口失败")
if not tomcat.add_host(config["project_name"], config["project_path"]):
return json_response(status=False, msg="添加失败")
# 有web服务且可以重启
if public.is_apache_nginx() and not isinstance(public.checkWebConfig(), str):
bind_extranet = 1
else:
bind_extranet = 0
if os.path.isfile(config["project_path"]):
path = os.path.basename(config["project_path"])
else:
path = config["project_path"]
project_config = {
'project_name': config["project_name"],
'bind_extranet': bind_extranet,
'domains': config['domains'],
'tomcat_version': config["tomcat_version"],
'java_type': 'neizhi',
'server_xml': '/usr/local/bt_mod_tomcat/tomcat%s/conf/server.xml' % config["tomcat_version"],
'port': int(tomcat.port()),
'auth': '1', # 默认开机自动启动
'logs': os.path.dirname(tomcat.log_file),
'ssl_path': '/www/wwwroot/java_node_ssl',
"proxy_info": [],
}
# 添加数据库信息
pdata = {
'name': config["project_name"],
'path': config["project_path"],
'ps': config["ps"],
'status': 1,
'type_id': 0,
'project_type': 'Java',
'project_config': json.dumps(project_config),
'addtime': public.getDate()
}
tomcat.save_config_xml()
project_id = public.M('sites').insert(pdata)
pdata["id"] = project_id
for domain in config["domains"]:
domain_name, port = domain.split(":")
public.M('domain').insert({
'name': domain_name,
'pid': project_id,
'port': port,
'addtime': public.getDate()
})
tomcat.restart()
pdata["project_config"] = project_config
if bind_extranet:
self.create_config(
pdata,
domains=[i.split(":") for i in config['domains']],
use_ssl=False)
return json_response(status=True, msg='项目创建成功')
@staticmethod
def check_site_tomcat_args(get) -> Union[Dict, str]:
jdk_path = None
try:
domain = get.domain.strip()
tomcat_version = int(get.tomcat_version)
project_path = get.project_path.strip()
if hasattr(get, "project_jdk"):
jdk_path = get.project_jdk.strip()
port = int(get.port)
run_user = get.run_user.strip()
ps = get.project_ps.strip()
except:
return "Parameter error"
if not utils.check_port(port):
return "端口已被使用"
if not is_domain(domain):
return "请输入正确的域名"
if not os.path.exists(project_path):
os.makedirs(project_path)
public.set_own(project_path, 'www')
if tomcat_version not in (7, 8, 9, 10):
return "请选择正确的Tomcat版本"
if jdk_path:
if not os.path.exists(jdk_path):
return "JDK路径不存在"
jdk_path = utils.normalize_jdk_path(jdk_path)
if not isinstance(jdk_path, str):
return "JDK路径错误"
if not utils.test_jdk(jdk_path):
return "JDK检查错误"
if run_user not in [i["username"] for i in RealUser().get_user_list()["data"]]:
return '请输入正确的启动用户'
domain_list, err = normalize_domain(domain)
if err:
return "<br>".join(["域名:{},错误信息:{}".format(i['domain'], i['msg']) for i in err])
else:
for d, p in domain_list:
if public.M('domain').where('name=?', d).count():
return '指定域名已存在: {}'.format(d)
domain = domain_list[0]
project_name = domain[0]
domain = "{}:{}".format(domain[0], domain[1])
return {
"project_name": project_name,
"project_jdk": jdk_path,
"run_user": run_user,
"port": port,
"ps": ps,
"domains": [domain, ],
"tomcat_version": tomcat_version,
"project_path": project_path,
'ssl_path': '/www/wwwroot/java_node_ssl',
}
def create_site_tomcat_project(self, get):
config = self.check_site_tomcat_args(get)
if isinstance(config, str):
return json_response(status=False, msg=config)
site_tomcat_path = os.path.join(self._site_tomcat_path, config["project_name"])
if os.path.exists(site_tomcat_path):
return json_response(status=False, msg="该网站已经存在。如想建立请删除%s" % site_tomcat_path)
# 首先需要先复制好文件过去
if not os.path.exists(site_tomcat_path):
os.makedirs(site_tomcat_path)
bt_tomcat_back = "/usr/local/bttomcat/tomcat_bak%d"
if not os.path.exists(bt_tomcat_back % config["tomcat_version"] + '/conf/server.xml'):
return json_response(False, "tomcat7的配置文件不存在请重新安装tomcat7")
public.ExecShell('cp -r %s/* %s && chown -R %s:%s %s' % (
bt_tomcat_back % int(config["tomcat_version"]), site_tomcat_path,
config["run_user"], config["run_user"], site_tomcat_path
))
tomcat = utils.site_tomcat(config["project_name"])
if not tomcat:
return json_response(status=False, msg="Tomcat未能初始化成功")
# server.xml
if os.path.exists(site_tomcat_path + '/conf/server.xml'):
tomcat.reset_tomcat_server_config(config["port"])
else:
os.system('rm -rf %s' % site_tomcat_path)
return json_response(False, "配置文件不存在请重新安装tomcat后尝试新建网站")
if tomcat.jdk_path != config["project_jdk"]:
res = tomcat.replace_jdk(config["project_jdk"])
if res:
os.system('rm -rf %s' % site_tomcat_path)
return json_response(status=False, msg="JDK替换失败")
log_path = "/www/wwwlogs/java/{}".format(config["project_name"])
if not os.path.exists(log_path) or os.path.isfile(log_path):
os.makedirs(log_path, mode=0o755)
tomcat.change_log_path(log_path, prefix=config["project_name"].replace(".", '_'))
if not tomcat.add_host(config["project_name"], config["project_path"]):
os.system('rm -rf %s' % site_tomcat_path)
return json_response(status=False, msg="添加失败")
# 有web服务且可以重启
if public.is_apache_nginx() and not isinstance(public.checkWebConfig(), str):
bind_extranet = 1
else:
bind_extranet = 0
if os.path.isfile(config["project_path"]):
path = os.path.basename(config["project_path"])
else:
path = config["project_path"]
project_config = {
'project_name': config["project_name"],
"project_jdk": config["project_jdk"],
'bind_extranet': bind_extranet,
'domains': config["domains"],
'tomcat_version': config["tomcat_version"],
'java_type': 'duli',
'server_xml': site_tomcat_path + "/conf/server.xml",
'port': config["port"],
"run_user": config["run_user"],
'logs': log_path,
"proxy_info": [],
}
pdata = {
'name': config["project_name"],
'path': config["project_path"],
'ps': config["ps"],
'status': 1,
'type_id': 0,
'project_type': 'Java',
'project_config': json.dumps(project_config),
'addtime': public.getDate()
}
tomcat.save_config_xml()
project_id = public.M('sites').insert(pdata)
pdata["id"] = project_id
for domain in config["domains"]:
domain_name, port = domain.split(":")
public.M('domain').insert({
'name': domain_name,
'pid': project_id,
'port': port,
'addtime': public.getDate()
})
tomcat.restart(by_user=config["run_user"])
pdata["project_config"] = project_config
if bind_extranet:
self.create_config(
pdata,
domains=[i.split(":") for i in config['domains']],
use_ssl=False)
return json_response(status=True, msg='项目创建成功')
def create_project(self, get):
try:
project_type = int(get.project_type)
except:
return json_response(status=False, msg="项目类型错误")
if project_type == 0:
return self.create_spring_boot_project(get)
elif project_type == 1:
return self.create_tomcat_project(get)
else:
return self.create_site_tomcat_project(get)
@staticmethod
def get_project_find(project_name: str) -> Optional[dict]:
project_info = public.M('sites').where('project_type=? AND name=?', ('Java', project_name)).find()
if not project_info:
return None
# 做旧项目的兼容性处理
project_info['project_config'] = json.loads(project_info['project_config'])
if "jmx_status" not in project_info['project_config']:
project_info['project_config']['jmx_status'] = False
if "nohup_log" not in project_info['project_config']:
project_info['project_config']['nohup_log'] = True
if "env_file" not in project_info['project_config']:
project_info['project_config']['env_file'] = ''
if "env_list" not in project_info['project_config']:
project_info['project_config']['env_list'] = []
if "static_path" in project_info['project_config'] and "static_info" not in project_info['project_config']:
project_info['project_config']['static_info'] = {
"path": project_info['project_config']['static_path'],
"status": True,
"index": "",
"use_try_file": True
}
public.M('sites').where("id=?", (project_info['id'],)).update(
{'project_config': json.dumps(project_info['project_config'])}
)
if "proxy_info" not in project_info['project_config']:
rsp = RealServerProxy(project_info)
proxy_list = rsp.get_proxy_list()
project_info['project_config']['proxy_info'] = proxy_list
if 'auth' in project_info['project_config'] and project_info['project_config']['auth'] in (1, "1") and \
"daemon_status" not in project_info['project_config']:
project_info['project_config']['daemon_status'] = True
if 'daemon_status' not in project_info['project_config']:
project_info['project_config']['daemon_status'] = False
return project_info
def modify_spring_boot_project(self, get, project_data: Optional[dict] = None):
if not project_data:
try:
project_name = self.get_project_find(get.project_name.strip())
except:
return json_response(status=False, msg="项目名称错误")
if not project_data:
return json_response(status=False, msg="The project does not exist")
else:
project_name = project_data['name']
change_flag = False
project_config = project_data['project_config']
if hasattr(get, 'run_user') and get.run_user.strip() != project_config['run_user']:
project_config['run_user'] = get.run_user.strip()
change_flag = True
if hasattr(get, 'project_jdk'):
input_jdk = utils.normalize_jdk_path(get.project_jdk.strip())
if not isinstance(input_jdk, str):
return json_response(False, 'JDK检测错误')
if input_jdk != project_config['project_jdk']:
project_config['project_jdk'] = input_jdk
change_flag = True
if hasattr(get, 'project_jar') and get.project_jar.strip() != project_config['project_jar']:
project_config['project_jar'] = get.project_jar.strip()
if not os.path.isfile(project_config['project_jar']):
return json_response(False, '项目jar包不存在')
project_config['jar_path'] = os.path.dirname(project_config['project_jar'])
change_flag = True
if hasattr(get, 'project_cmd') and get.project_cmd.strip():
if get.project_cmd.strip() != project_config['project_cmd']:
project_config['project_cmd'] = get.project_cmd.strip()
change_flag = True
else:
return json_response(False, '缺少project_cmd参数')
if hasattr(get, 'daemon_status'):
daemon_status = utils.js_value_to_bool(get.daemon_status)
if daemon_status != project_config['daemon_status']:
project_config['daemon_status'] = daemon_status
change_flag = True
# 检查jar包是否在cmd中
if project_config['project_cmd'].find(get.project_jar.strip()) == -1:
return json_response(False, '项目jar包名称不在项目启动命令中请检查')
if hasattr(get, 'jmx_status') and utils.js_value_to_bool(get.jmx_status) != project_config['jmx_status']:
project_config['jmx_status'] = utils.js_value_to_bool(get.jmx_status)
change_flag = True
if hasattr(get, "env_file") and get.env_file.strip() != project_config['env_file']:
project_config['env_file'] = get.env_file.strip()
if project_config['env_file'] and not os.path.exists(project_config['env_file']):
return json_response(False, '项目环境文件不存在')
change_flag = True
if hasattr(get, "env_list"):
env_list = get.env_list
if isinstance(env_list, str):
try:
env_list = json.loads(env_list)
except:
return json_response(False, '项目环境变量格式错误')
if not isinstance(env_list, list):
return json_response(False, '项目环境变量格式错误')
if env_list != project_config['env_list']:
project_config['env_list'] = env_list
change_flag = True
if hasattr(get, 'watch_file'):
project_config['watch_file'] = utils.js_value_to_bool(get.watch_file)
if project_config['watch_file']:
add_project_watch(p_name=get.project_name.strip(),
p_type="java",
site_id=project_data["id"],
watch_path=get.project_jar.strip())
else:
del_project_watch(get.project_name.strip())
if change_flag:
project_config["change_flag"] = True
pdata = {
'name': project_name,
'path': get.project_jar.strip(),
'ps': get.project_ps.strip(),
'project_config': json.dumps(project_config)
}
public.M('sites').where('name=?', (get.project_name,)).update(pdata)
return json_response(True, '项目修改成功,重启后生效')
def modify_tomcat_project(self, get, project_data: Optional[dict] = None):
if not project_data:
try:
project_name = self.get_project_find(get.project_name.strip())
except:
return json_response(status=False, msg="项目名称错误")
if not project_data:
return json_response(status=False, msg="The project does not exist")
else:
project_name = project_data['name']
project_config = project_data['project_config']
tomcat = utils.bt_tomcat(project_config["tomcat_version"])
flag = False
# 更换JDK
if hasattr(get, 'project_jdk') and get.project_jdk:
jdk_path = utils.normalize_jdk_path(get.project_jdk.strip())
if not isinstance(jdk_path, str):
return json_response(False, 'JDK检测错误')
if jdk_path != tomcat.jdk_path:
if not utils.test_jdk(jdk_path):
return json_response(False, '当前JDK不可用')
res = tomcat.replace_jdk(jdk_path)
if not res:
return json_response(False, res)
flag = True
if hasattr(get, 'project_path'):
if get.project_path.strip() == project_data['path']:
pass
else:
if not tomcat.set_host_path_by_name(project_name, get.project_path.strip()):
return json_response(False, '项目路径设置失败')
project_data['path'] = get.project_path.strip()
# 更换描述
if hasattr(get, 'project_ps'):
if get.project_ps.strip() != project_data['ps']:
project_data['ps'] = get.project_ps.strip()
if flag:
tomcat.restart()
pdata = {
'path': project_data['path'],
'ps': project_data['ps'],
}
public.M('sites').where('name=?', (get.project_name,)).update(pdata)
return json_response(True, '项目修改成功')
def modify_site_tomcat_project(self, get, project_data: Optional[dict] = None):
if not project_data:
try:
project_name = self.get_project_find(get.project_name.strip())
except:
return json_response(status=False, msg="项目名称错误")
if not project_data:
return json_response(status=False, msg="The project does not exist")
else:
project_name = project_data['name']
project_config = project_data['project_config']
tomcat = utils.site_tomcat(project_name)
if not tomcat:
return json_response(False, '项目的Tomcat已被删除请尝试修复项目')
flag = False
# 更换JDK
if hasattr(get, 'project_jdk') and get.project_jdk:
jdk_path = utils.normalize_jdk_path(get.project_jdk.strip())
if not isinstance(jdk_path, str):
return json_response(False, 'JDK检测错误')
if jdk_path != tomcat.jdk_path:
if not utils.test_jdk(jdk_path):
return json_response(False, '当前JDK不可用')
res = tomcat.replace_jdk(jdk_path)
if isinstance(res, str):
return json_response(False, res)
flag = True
project_config["project_jdk"] = jdk_path
if hasattr(get, 'port'):
try:
port = int(get.port)
except:
return json_response(False, '端口信息错误')
if port != tomcat.port():
if not utils.check_port(port):
return json_response(False, '端口已被占用')
res = tomcat.set_port(port)
if not res:
return json_response(False, '端口设置失败')
tomcat.save_config_xml()
flag = True
project_config["port"] = port
# 更换描述
if hasattr(get, 'project_ps'):
if get.project_ps.strip() != project_data['ps']:
project_data['ps'] = get.project_ps.strip()
if hasattr(get, 'project_path'):
if get.project_path.strip() != project_data['path']:
if not tomcat.set_host_path_by_name(project_name, get.project_path.strip()):
return json_response(False, '项目路径设置失败')
project_data['path'] = get.project_path.strip()
flag = True
if hasattr(get, 'run_user'):
if "run_user" not in project_config:
project_config["run_user"] = "root"
if get.run_user.strip() != project_config['run_user']:
run_user = get.run_user.strip()
if run_user not in [i["username"] for i in RealUser().get_user_list()["data"]]:
return json_response(False, '请输入正确的启动用户')
else:
project_config["run_user"] = run_user
flag = True
if flag:
tomcat.restart(by_user=project_config["run_user"])
pdata = {
'path': project_data['path'],
'ps': project_data['ps'],
'project_config': json.dumps(project_config),
}
public.M('sites').where('name=?', (get.project_name,)).update(pdata)
return json_response(True, '项目修改成功')
def modify_project(self, get):
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(status=False, msg="The project does not exist")
project_config = project_data["project_config"]
if project_config["java_type"] == "springboot":
return self.modify_spring_boot_project(get, project_data)
elif project_config["java_type"] == "duli":
return self.modify_site_tomcat_project(get, project_data)
else:
return self.modify_tomcat_project(get, project_data)
def get_project_pid(self, project_data: dict) -> Optional[int]:
# 从pid文件中获取项目pid
project_config = project_data["project_config"]
if project_config["java_type"] == "springboot":
pid_file = project_config["pids"]
pid = None
if os.path.isfile(pid_file):
try:
pid = int(public.readFile(pid_file))
except:
pass
elif project_config["java_type"] == "neizhi":
pid = utils.bt_tomcat(project_config["tomcat_version"]).pid()
else:
pid = utils.site_tomcat(project_data["name"]).pid()
if not pid and project_config["java_type"] == "springboot":
try:
return self._get_pid_by_command(project_data)
except:
return None
try:
psutil.Process(pid)
except:
return None
return pid
@staticmethod
def _get_pid_by_command(project_data: dict) -> Optional[int]:
project_config = project_data["project_config"]
server_name = "spring_" + project_config["project_name"] + project_config.get("server_name_suffix", "")
print(server_name)
server_admin = RealServer()
pid = server_admin.get_daemon_pid(server_name)["data"]
if pid == 0:
time.sleep(0.5)
pid = server_admin.get_daemon_pid(server_name)["data"]
if isinstance(pid, int):
try:
p = psutil.Process(pid)
if p.is_running():
public.writeFile(project_data["project_config"]['pids'], str(pid))
return pid
except:
pass
if project_config["java_type"] == "springboot":
jdk_path = utils.normalize_jdk_path(project_config['project_jdk'])
project_jar = project_config['project_jar']
jar_name = os.path.basename(project_jar)
jar_cmd = project_config['project_cmd']
port_rep = re.search(r"--server\.port=\d+", jar_cmd)
pids = []
for pro in psutil.process_iter(['pid', 'exe', 'cmdline']):
if pro.status() == "zombie":
continue
try:
if port_rep and port_rep.group() not in pro.cmdline():
continue
if jdk_path == utils.normalize_jdk_path(pro.exe()) and any((jar_name in i for i in pro.cmdline())):
pids.append(pro.pid)
except:
pass
if not pids:
return None
running_pid = []
for pid in pids:
if pid in psutil.pids():
running_pid.append(pid)
if len(running_pid) == 1:
public.writeFile(project_data["project_config"]['pids'], str(running_pid[0]))
return running_pid[0]
for pid in running_pid:
p = psutil.Process(pid)
if p.ppid() not in running_pid:
public.writeFile(project_data["project_config"]['pids'], str(pid))
return pid
return None
def project_process(self, project_data) -> Optional[psutil.Process]:
pid = self.get_project_pid(project_data)
if not pid:
return None
try:
return psutil.Process(pid)
except:
return None
def start_spring_boot_project(self, project_data: dict, wait: bool = True):
change_flag = False
project_config = project_data['project_config']
if "change_flag" in project_config:
change_flag = project_config.get("change_flag", False)
del project_config["change_flag"]
public.M("sites").where("id=?", (project_data["id"],)).update(
{"project_config": json.dumps(project_config)}
)
res = self._start_spring_boot_project(project_data, change_flag, need_wait=wait)
if res["status"] is True:
utils.start_by_user(project_data["id"])
return res
def start_project(self, get):
try:
project_data = self.get_project_find(get.project_name)
except:
return json_response(False, '项目名称参数错误')
if not project_data:
return json_response(False, 'The project does not exist')
p = self.project_process(project_data)
if p and p.is_running():
return json_response(False, '项目已启动')
project_config = project_data['project_config']
if project_config["java_type"] == "springboot":
return self.start_spring_boot_project(project_data)
elif project_config["java_type"] == "neizhi":
res = utils.bt_tomcat(project_config["tomcat_version"]).start()
if not res:
return json_response(False, '项目启动失败')
else:
tomcat = utils.site_tomcat(project_config["project_name"])
if not tomcat:
return json_response(False, '独立项目的Tomcat文件丢失请尝试修复项目')
if not tomcat.running():
res = tomcat.start()
if not res:
return json_response(False, '项目启动失败')
utils.start_by_user(project_data["id"])
return json_response(True, "项目启动成功")
def stop_project(self, get):
try:
project_data = self.get_project_find(get.project_name)
except:
return json_response(False, '项目名称参数错误')
if not project_data:
return json_response(False, 'The project does not exist')
project_config = project_data['project_config']
if project_config["java_type"] == "springboot":
server_name = "spring_" + project_config["project_name"] + project_config.get("server_name_suffix", "")
s_admin = RealServer()
if s_admin.daemon_status(server_name)["msg"] == "服务不存在!":
self.stop_by_kill_pid(project_data)
if os.path.isfile(project_config["pids"]):
os.remove(project_config["pids"])
else:
s_admin.daemon_admin(server_name, "stop")
utils.stop_by_user(project_data["id"])
return json_response(True, msg="项目停止指令已执行")
elif project_config["java_type"] == "neizhi":
res = utils.bt_tomcat(project_config["tomcat_version"]).stop()
if not res:
return json_response(False, '项目停止失败')
else:
tomcat = utils.site_tomcat(project_config["project_name"])
if not tomcat:
return json_response(False, '独立项目的Tomcat文件丢失请尝试修复项目')
if tomcat.running():
res = tomcat.stop()
if not res:
return json_response(False, '项目停止失败')
utils.stop_by_user(project_data["id"])
return json_response(True, "项目停止成功")
def stop_by_kill_pid(self, project_data):
pid = self.get_project_pid(project_data)
if not pid:
return
try:
p = psutil.Process(pid)
p.kill()
except:
pass
def restart_project(self, get):
try:
project_data = self.get_project_find(get.project_name)
except:
return json_response(False, '项目名称参数错误')
if not project_data:
return json_response(False, 'The project does not exist')
project_config = project_data['project_config']
if project_config["java_type"] == "springboot":
s_admin = RealServer()
server_name = "spring_" + project_config["project_name"] + project_config.get("server_name_suffix", "")
if s_admin.daemon_status(server_name)["msg"] == "服务不存在!":
self.stop_by_kill_pid(project_data)
if os.path.isfile(project_config["pids"]):
os.remove(project_config["pids"])
return self._start_spring_boot_project(project_data, write_systemd_file=True)
if "change_flag" in project_config and project_config.get("change_flag", False):
del project_config["change_flag"]
s_admin.daemon_admin(server_name, "stop")
s_admin.del_daemon(server_name)
self.stop_by_kill_pid(project_data)
if os.path.isfile(project_config["pids"]):
os.remove(project_config["pids"])
public.M("sites").where("id=?", (project_data["id"],)).update(
{"project_config": json.dumps(project_config)}
)
return self._start_spring_boot_project(project_data, write_systemd_file=True)
else:
return self._start_spring_boot_project(project_data, write_systemd_file=False)
self.stop_project(get)
time.sleep(0.5)
self.start_project(get)
return json_response(True, "项目重启已执行")
def project_list(self, get):
"""取项目列表"""
p = 1
limit = 12
callback = ""
order = "id desc"
search = ""
type_id = None
try:
if hasattr(get, "p"):
p = int(get.p)
if hasattr(get, "limit"):
limit = int(get.limit)
if hasattr(get, "callback"):
callback = get.callback.strip()
if hasattr(get, "order"):
order = get.order.strip()
if hasattr(get, "search"):
search = get.search.strip()
if hasattr(get, "type_id") and get.type_id:
type_id = int(get.type_id)
except:
return json_response(False, '参数错误')
type_filter = ''
if type_id is not None:
type_filter = ' AND type_id=?'
if search:
search = "%{}%".format(search)
if type_filter:
where_str = 'project_type=? AND (name LIKE ? OR ps LIKE ?)' + type_filter
where_args = ('Java', search, search, type_id)
else:
where_str = 'project_type=? AND (name LIKE ? OR ps LIKE ?)'
where_args = ('Java', search, search)
count = public.M('sites').where(where_str, where_args).count()
data = public.get_page(count, p, limit, callback)
data['data'] = public.M('sites').where(where_str, where_args).limit(
data['shift'] + ',' + data['row']).order(order).select()
else:
if type_filter:
where_str = 'project_type=?' + type_filter
where_args = ('Java', type_id)
else:
where_str = 'project_type=?'
where_args = ('Java',)
count = public.M('sites').where(where_str, where_args).count()
data = public.get_page(count, p, limit, callback)
data['data'] = public.M('sites').where(where_str, where_args).limit(
data['shift'] + ',' + data['row']).order(order).select()
for project_data in data['data']:
project_config = json.loads(project_data['project_config'])
project_data['project_config'] = project_config
# 如果内置项目 或 独立项目 的tomcat配置文件丢失
if project_config['java_type'] == 'neizhi' or project_config['java_type'] == 'duli':
if not os.path.exists(project_config['server_xml']):
project_data['server_file_status'] = False
else:
project_data['server_file_status'] = True
for i in range(len(data['data'])):
self.get_project_stat(data['data'][i])
return data
def get_project_stat(self, project_data: dict) -> dict:
if isinstance(project_data['project_config'], str):
project_config = json.loads(project_data['project_config'])
project_data['project_config'] = project_config
project_data["pid"] = self.get_project_pid(project_data)
if project_data["project_config"]["java_type"] == "springboot":
project_data["project_config"]["watch_file"] = use_project_watch(project_data["name"])
project_data["listen"] = []
project_data["ssl"] = RealSSLManger("java_").get_site_ssl_info(project_data["name"])
if not project_data["ssl"]:
project_data["ssl"] = -1
if project_data["pid"]:
project_data["pid_info"] = self.real_process.get_process_info_by_pid(project_data["pid"])["data"]
listen = []
if project_data["pid_info"] and "connections" in project_data["pid_info"]:
for connection in project_data["pid_info"]["connections"]:
if connection["status"] == "LISTEN":
listen.append(connection["local_port"])
project_data["listen"] = listen
if project_data['project_config']["java_type"] == "springboot":
project_data['project_config']["port"] = ",".join([str(i) for i in listen])
else:
project_data["pid_info"] = None
project_data["starting"] = False
if project_data["pid"] and not project_data["listen"]:
project_data["starting"] = True
if os.path.exists("{}/nginx/{}.conf".format(self._vhost_path, project_data["name"])) or \
os.path.exists("{}/apache/{}.conf".format(self._vhost_path, project_data["name"])):
project_data["bind_extranet"] = True
else:
project_data["bind_extranet"] = False
if project_data['project_config']["java_type"] == "duli" and "project_jdk" not in project_data['project_config']:
tomcat = utils.site_tomcat(project_data["name"])
if tomcat:
project_data['project_config']["project_jdk"] = tomcat.jdk_path
else:
project_data['project_config']["project_jdk"] = "/usr/local/btjdk/jdk8"
return project_data
@staticmethod
def _project_domain_list(project_id: int):
return public.M('domain').where('pid=?', (project_id,)).select()
def project_domain_list(self, get):
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist')
data = self._project_domain_list(project_data['id'])
return json_response(True, data=data)
def add_domains(self, get):
""" 为指定项目添加域名 """
try:
if isinstance(get.domains, str):
domains = json.loads(get.domains)
else:
domains = get.domains
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not isinstance(domains, list):
return json_response(False, '域名参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist')
project_id = project_data['id']
project_name = project_data["name"]
domain_list, err = normalize_domain(*domains)
if err:
return "<br>".join(["域名:{},错误信息:{}".format(i['domain'], i['msg']) for i in err])
res_domains = []
for d, p in domain_list:
if not public.M('domain').where('name=?', (d,)).count():
public.M('domain').add('name,pid,port,addtime', (d, project_id, p, public.getDate()))
self.write_project_log('成功添加域名{}到项目{}'.format(d, get.project_name))
res_domains.append({"name": d, "status": True, "msg": '添加成功'})
else:
self.write_project_log('添加域名错误,域名{}已存在'.format(d))
res_domains.append({"name": d, "status": False, "msg": '添加失败,域名{}已存在'.format(d)})
all_domain = self._project_domain_list(project_id)
print(all_domain)
# 写配置文件
if utils.js_value_to_bool(project_data["project_config"]["bind_extranet"]):
res = self._set_domain(project_data, [(i["name"], str(i["port"])) for i in all_domain])
if res:
return json_response(True, msg="域名记录成功,但配置文件写入时失败:" + res, data=res_domains)
return json_response(True, msg="添加成功", data=res_domains)
def remove_domains(self, get):
""" 移除指定项目中的域名 """
try:
if isinstance(get.domains, str):
remove_list = json.loads(get.domains)
else:
remove_list = get.domains
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist')
if not isinstance(remove_list, list):
return json_response(False, '域名参数错误')
all_domain = self._project_domain_list(project_data["id"])
if not all_domain:
return json_response(False, '指定项目中没有域名可被删除')
bind_extranet = False
if os.path.exists("{}/nginx/{}.conf".format(self._vhost_path, project_data["name"])) or \
os.path.exists("{}/apache/{}.conf".format(self._vhost_path, project_data["name"])):
bind_extranet = True
if len(all_domain) == 1 and bind_extranet:
return json_response(False, '请至少保留一个域名,如无需外网映射,关闭即可', data=[{
"domain": all_domain[0]["name"],
"status": False,
"msg": "无法删除最后一个域名"
}])
all_domain.sort(key=lambda x: x["id"], reverse=True)
all_domain_id_dict = {i["id"]: i for i in all_domain}
del_id_list = [i for i in all_domain_id_dict if i in remove_list]
res_data = []
# 说明选中了所有域名,这时需要保持一个默认域名
default_domain = None
if len(all_domain_id_dict) == len(del_id_list) and bind_extranet:
default_domain = all_domain[0]
del_id_list.remove(default_domain["id"])
for i in del_id_list:
public.M('domain').delete(id=i)
res_data.append(
{
"domain": all_domain_id_dict[i]["name"],
"status": True,
"msg": "删除成功"
}
)
self.write_project_log('成功删除域名{}'.format([all_domain_id_dict[i]["name"] for i in del_id_list]))
if default_domain:
res_data.append(
{
"domain": default_domain["name"],
"status": False,
"msg": "无法删除最后一个域名"
}
)
if bind_extranet:
now_domain = self._project_domain_list(project_data["id"])
# 写配置文件
res = self._set_domain(project_data, [(i["name"], str(i["port"])) for i in now_domain])
if res:
return json_response(False, msg="域名记录删除成功,但配置文件写入时失败:" + res, data=res_data)
return json_response(True, msg="Successfully delete", data=res_data)
def bind_extranet(self, get):
"""开放外网映射"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
if not public.is_apache_nginx():
return json_response(False, "未安装Nginx")
err_msg = public.checkWebConfig()
if isinstance(err_msg, str):
msg = 'WEB服务器配置配置文件错误ERROR:<br><font style="color:red;">' + \
err_msg.replace("\n", '<br>') + '</font>'
return json_response(False, msg=msg)
res = self._open_config_file(project_data)
if isinstance(res, str):
return json_response(False, msg=res)
project_config = project_data["project_config"]
project_config["bind_extranet"] = 1
public.M('sites').where('id=?', (project_data["id"],)).update(
{"project_config": json.dumps(project_config)}
)
return json_response(True, msg="Successfully set")
def unbind_extranet(self, get):
"""关闭外网映射"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_config = project_data["project_config"]
self._close_apache_config_file(project_data)
project_config["bind_extranet"] = 0
public.M('sites').where('id=?', (project_data["id"],)).update(
{"project_config": json.dumps(project_config)}
)
return json_response(True, msg="Successfully set")
def remove_project(self, get):
"""删除指定项目"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_config = project_data["project_config"]
project_name = project_data["name"]
if project_config['java_type'] == 'duli':
tomcat = utils.site_tomcat(project_name)
# 关闭独立项目
if tomcat:
tomcat.stop()
if os.path.exists(tomcat.path):
shutil.rmtree(tomcat.path)
elif project_config['java_type'] == 'neizhi':
# 删除tomcat站点
tomcat = utils.bt_tomcat(project_config["tomcat_version"])
tomcat.remove_host(project_name)
tomcat.save_config_xml()
if tomcat.running():
tomcat.restart()
elif project_config['java_type'] == 'springboot':
# 停止项目
server_name = "spring_" + project_config["project_name"] + project_config.get("server_name_suffix", "")
s_admin = RealServer()
s_admin.daemon_admin(server_name, "stop")
s_admin.del_daemon(server_name)
pid_file = project_config['pids']
if os.path.exists(pid_file):
os.remove(pid_file)
script_file = project_config['scripts']
if os.path.exists(script_file):
os.remove(script_file)
env_path = "{}/env/{}.env".format(self._java_project_vhost, project_config["project_name"])
if os.path.exists(env_path):
os.remove(env_path)
log_file = project_config['logs']
if os.path.exists(log_file):
os.remove(log_file)
else:
return json_response(False, '项目类型错误')
threading.Thread(target=remove_sites_service_config, args=(project_name, "java_")).start()
public.M('domain').where('pid=?', (project_data['id'],)).delete()
public.M('sites').where('name=?', (project_name,)).delete()
self.write_project_log('删除Java项目{}'.format(get.project_name))
return json_response(True, '删除项目成功')
def config_file_list(self, get):
"""获取配置文件列表"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_name = project_data["name"]
res_list = []
bind_extranet = int(project_data["project_config"]["bind_extranet"]) != 0
if bind_extranet:
if public.get_webserver() == "nginx":
config_file = "{}/nginx/java_{}.conf".format(self._vhost_path, project_name)
res_list.append(
{
"name": "nginx配置文件",
"path": config_file,
"status": os.path.exists(config_file),
"type": "server"
}
)
else:
config_file = "{}/apache/java_{}.conf".format(self._vhost_path, project_name)
res_list.append(
{
"name": "apache配置文件",
"path": config_file,
"status": os.path.exists(config_file),
"type": "server"
}
)
rewrite_file = "{}/rewrite/java_{}.conf".format(self._vhost_path, project_name)
res_list.append(
{
"name": "伪静态配置文件",
"path": rewrite_file,
"status": os.path.exists(rewrite_file),
"type": "rewrite"
}
)
p_list = RealProxy("java_").get_proxy_list(public.to_dict_obj({"sitename": project_name}))
f, r_list = RealRedirect("java_").get_redirect_list(public.to_dict_obj({"sitename": project_name}))
for p in p_list:
res_list.append({
"name": "反向代理【{}".format(p["proxyname"]),
"path": p["proxy_conf_file"],
"status": os.path.exists(p["proxy_conf_file"]),
"type": "proxy"
})
if f:
for r in r_list:
res_list.append({
"name": "重定向",
"path": r["redirect_conf_file"],
"status": os.path.exists(r["redirect_conf_file"]),
"type": "redirect"
})
if project_data["project_config"]["java_type"] == "neizhi":
tomcat = utils.bt_tomcat(project_data["project_config"]["tomcat_version"])
res_list.append({
"name": "Tomcat【{}】配置文件".format(project_data["project_config"]["tomcat_version"]),
"path": os.path.join(tomcat.path, "conf/server.xml"),
"status": tomcat.installed,
"type": "tomcat"
})
elif project_data["project_config"]["java_type"] == "duli":
tomcat = utils.site_tomcat(project_data["name"])
res_list.append({
"name": "Tomcat配置文件",
"path": os.path.join(tomcat.path, "conf/server.xml"),
"status": tomcat.installed,
"type": "tomcat"
})
else:
t = time.time()
pid = self.get_project_pid(project_data)
if not pid:
pid = 0
spc = SpringConfigParser(
jar_path=project_data["project_config"]["project_jar"],
process=pid,
)
used, _ = spc.app_config()
for i, _ in used:
if i == "命令行或环境变量":
continue
profile = os.path.basename(i)[len(spc.config_name):] # 取出 - + profile + 后缀部分
if profile in (".yml", ".yaml", ".properties"):
profile = ""
else:
profile = profile.rsplit(".", 1)[0]
res_list.append({
"name": "Spring配置" + profile,
"path": i,
"status": True,
"type": "local_spring" if i.startswith("/") else "spring",
"data": spc.raw_data.get(i, "")
})
sort_tuple = {
"local_spring": 10,
"spring": 9,
"tomcat": 8,
"server": 7,
"proxy": 6,
"redirect": 5,
"rewrite": 4,
}
res_list.sort(key=lambda x: sort_tuple[x["type"]], reverse=True)
return json_response(True, data=res_list)
# 未使用
def project_log_list(self, get):
"""获取日志文件列表"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_name = project_data["name"]
res = RealLogMgr(conf_prefix="java_").get_site_log_path(public.to_dict_obj({"sitename": project_name}))
res_list = []
if isinstance(res, str):
res_list.extend([
{"type": "access", "path": None, "log_size": 0, "msg": "无法从配置文件中获取日志文件路径"},
{"type": "error", "path": None, "log_size": 0, "msg": "无法从配置文件中获取错误日志文件路径"}
])
else:
access_file = res["log_file"]
error_file = res["error_log_file"]
access_file_size = error_file_size = 0
if os.path.isfile(access_file):
access_file_size = os.path.getsize(access_file)
if os.path.isfile(error_file):
error_file_size = os.path.getsize(error_file)
res_list.extend([
{"type": "access", "path": access_file, "log_size": access_file_size, "msg": ""},
{"type": "error", "path": error_file, "log_size": error_file_size, "msg": ""}
])
project_config = project_data["project_config"]
if project_config["java_type"] == "springboot":
log_file = project_config['logs']
if not os.path.isfile(log_file):
pass
def get_command(self, get):
"""获取命令, 包含设置和取消jmx的设置"""
project_cmd = None
jmx_status = None
try:
if hasattr(get, "project_cmd"):
project_cmd = get.project_cmd.strip()
if hasattr(get, "jmx_status"):
jmx_status = utils.js_value_to_bool(get.jmx_status)
project_jdk = utils.normalize_jdk_path(get.project_jdk.strip())
project_jar = get.project_jar.strip()
except json.JSONDecodeError:
return json_response(False, '参数错误')
if not isinstance(project_jdk, str):
return json_response(False, '项目JDK路径不存在')
project_jdk = os.path.join(project_jdk, "bin/java")
if not os.path.isfile(project_jdk):
return json_response(False, '项目JDK不存在')
if not os.path.isfile(project_jar):
return json_response(False, '项目jar不存在')
if not isinstance(project_cmd, str) and project_cmd:
cmd = '{} -jar {} -Xmx1024M -Xms256M'.format(project_jdk, project_jar)
cmd = self._build_jmx_cmd(cmd, jmx_status)
else:
cmd = self._build_jmx_cmd(project_cmd, jmx_status)
return json_response(True, data=cmd)
def set_project_log_status(self, get):
"""设置项目日志是否开启"""
try:
project_data = self.get_project_find(get.project_name.strip())
status = utils.js_value_to_bool(get.status)
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
if project_data["project_config"]["java_type"] == "springboot":
project_config = project_data["project_config"]
project_config["nohup_log"] = status
project_config["change_flag"] = True
pdata = {
'project_config': json.dumps(project_config)
}
public.M('sites').where('id=?', (project_data["id"],)).update(pdata)
return json_response(True, "修改成功, 重启项目后生效")
else:
return json_response(False, "非springboot项目无法关闭")
def get_jmx_status(self, get):
"""设置项目日志是否开启"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_config = project_data["project_config"]
if not project_config["java_type"] == "springboot":
return json_response(False, "目前支持springboot 项目的jmx 监控")
pid = self.get_project_pid(project_data)
if not pid:
return json_response(False, "未启动的项目不能获取jmx信息")
jmx_info = self.get_jmx_data_by_pid(pid)
if not jmx_info:
return json_response(False, "项目未启用jmx无法获取jmx信息")
jmx_url = 'service:jmx:rmi:///jndi/rmi://{}:{}/jmxrmi'.format(jmx_info["host"], jmx_info["port"])
from mod.project.java.jmxquery import JMXConnection, JMXQuery
try:
# 创建 JMXConnection
# JMX 连接信息
jmxConnection = JMXConnection(
connection_uri=jmx_url,
java_path=os.path.join(project_config["project_jdk"], "bin/java")
)
jmxQuery = [JMXQuery("*:*")]
# 执行查询
metrics = jmxConnection.query(jmxQuery)
except Exception:
public.print_log(public.get_error_info())
return json_response(False, "连接失败! {}".format(jmx_url))
# 创建 JMX 查询
jmx_status_info = {}
type_list = ["MemoryPool", "GarbageCollector"]
percent_list = ["SystemCpuLoad", "ProcessCpuLoad"]
microsecond_list = [
"StartTime", "Uptime", "endTime", "startTime", "CollectionTime", "CurrentThreadCpuTime",
"CurrentThreadUserTime", "endTime", "startTime", "CollectionTime", "TotalCompilationTime",
]
nanoseconds_list = ["ProcessCpuTime", ]
size_list = ["FreePhysicalMemorySize", "TotalPhysicalMemorySize", "committed", "init", "max", "used"]
value_dict = {
"True": "",
"False": "",
"None": "",
}
# 解析结果
for metric in metrics:
java_type_obj = re.search(r"type=([\w\s]+)", metric.mBeanName)
if not java_type_obj:
continue
java_type = java_type_obj.group(1)
name_obj = re.search(r"name=([\w\s]+)", metric.mBeanName)
name = None
if name_obj:
name = name_obj.group(1)
if jmx_status_info.get(java_type) is None:
if java_type in type_list:
jmx_status_info[java_type] = []
else:
jmx_status_info[java_type] = {}
type_info: Union[Dict[str, Any], List[Dict[str, Any]]] = jmx_status_info[java_type]
if name is not None:
name = name.replace(" ", "_")
if isinstance(type_info, list):
for info in type_info:
if info["name"] == name:
type_info = info
break
else:
info = {"name": name}
type_info.append(info)
type_info = info
else:
if type_info.get(name) is None:
type_info[name] = {}
type_info = type_info[name]
value = value_dict.get(str(metric.value))
if value is None:
value = metric.value
if metric.attributeKey:
if metric.attribute is not None and type_info.get(metric.attribute) is None:
type_info[metric.attribute] = {}
if value == -1:
value = "无限制"
elif metric.attributeKey in size_list:
value = public.to_size(value)
elif metric.attributeKey in microsecond_list:
value = datetime.fromtimestamp(int(value) / 1000).strftime('%Y-%m-%d %H:%M:%S')
elif metric.attributeKey in nanoseconds_list:
value = "{}".format(int(value) / 1e9)
type_info[metric.attribute][metric.attributeKey] = value
else:
if metric.attribute in size_list:
value = public.to_size(value)
elif metric.attribute in percent_list:
value = "{}%".format(round(int(value) * 100, 2))
elif metric.attribute in microsecond_list:
value = datetime.fromtimestamp(int(value) / 1000).strftime('%Y-%m-%d %H:%M:%S')
elif metric.attribute in nanoseconds_list:
value = "{}".format(int(value) / 1e9)
type_info[metric.attribute] = value
return json_response(True, data=jmx_status_info)
@staticmethod
def get_jmx_data_by_pid(pid) -> Optional[dict]:
try:
p = psutil.Process(pid)
cmd_line = p.cmdline()
except:
return None
data = {
"port": "",
"host": "127.0.0.1"
}
for i in cmd_line:
if i.startswith("-Dcom.sun.management.jmxremote.port"):
data["port"] = i.split("=")[1]
if i.startswith("-Djava.rmi.server.hostname"):
data["host"] = i.split("=")[1]
if not data["port"]:
return None
return data
def get_project_info(self, get):
"""设置项目日志是否开启"""
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.project_name))
project_data = self.get_project_stat(project_data)
return json_response(True, data=project_data)
# 上传版本
def upload_version(self, get):
"""
上传压缩包并存储为版本
"""
if not hasattr(get, 'sitename'):
return json_response(False, 'The project name cannot be empty')
if not hasattr(get, 'version'):
return json_response(False, '版本号不能为空')
if not hasattr(get, 'ps'):
get.ps = ''
try:
upload_files = os.path.join("/tmp", get.f_name)
if "/www/server/panel/class" not in sys.path:
sys.path.insert(0, "/www/server/panel/class")
from files import files
file_obj = files()
ff = file_obj.upload(get)
if type(ff) == int:
return ff
if not ff['status']:
return json_response(False, ff['msg'])
output_dir = str(os.path.join('/tmp', public.GetRandomString(16)))
os.makedirs(output_dir, 777)
is_jar_war = os.path.splitext(upload_files)[-1] in (".jar", ".war")
if not self.extract_archive(upload_files, output_dir)[0] and not is_jar_war:
return json_response(False, '解压失败,仅支持zip,tar.gz,tar,bz2,gz格式的压缩包')
version_tool = VersionTool()
if not is_jar_war:
if len(os.listdir(output_dir)) == 1:
real_output_dir = str(os.path.join(output_dir, os.listdir(output_dir)[0]))
if os.path.isdir(real_output_dir):
output_dir = real_output_dir
res = version_tool.publish_by_src_path(get.sitename, output_dir, get.version, get.ps, sync=True)
public.ExecShell('rm -rf {}'.format(output_dir))
public.ExecShell('rm -rf {}'.format(upload_files))
else:
res = version_tool.publish_by_file(get.sitename, upload_files, get.version, get.ps)
public.ExecShell('rm -rf {}'.format(upload_files))
if res is None:
return public.returnResult(True, '添加成功')
return json_response(False, '添加失败' + res)
except:
return json_response(False, traceback.format_exc())
@staticmethod
def extract_archive(file_path, output_dir):
try:
import tarfile
import zipfile
import gzip
import bz2
name = os.path.basename(file_path)
if name.endswith('.tar.gz'):
with tarfile.open(file_path, 'r:gz') as tar:
tar.extractall(output_dir)
elif name.endswith('.zip'):
with zipfile.ZipFile(file_path, 'r') as zip_ref:
zip_ref.extractall(output_dir)
elif name.endswith('.gz'):
with gzip.open(file_path, 'rb') as f_in, open(os.path.join(output_dir, name[:-3]), 'wb') as f_out:
shutil.copyfileobj(f_in, f_out)
elif name.endswith('.tar'):
with tarfile.open(file_path, 'r') as tar:
tar.extractall(output_dir)
elif name.endswith('.bz2'):
with open(file_path, 'rb') as f_in, open(os.path.join(output_dir, name[:-4]), 'wb') as f_out:
with bz2.BZ2File(f_in) as bz:
shutil.copyfileobj(bz, f_out)
else:
return False, '文件格式错误.'
except:
return False, '解压失败'
return True, '解压成功'
# 获取列表
@staticmethod
def get_version_list(get):
if not hasattr(get, 'sitename'):
return public.returnResult(False, 'The project name cannot be empty')
version_tool = VersionTool()
return json_response(True, data=version_tool.version_list(get.sitename))
# 删除版本
@staticmethod
def remove_version(get):
if not hasattr(get, 'sitename'):
return json_response(False, 'The project name cannot be empty')
if not hasattr(get, 'version'):
return json_response(False, '版本号不能为空')
version_tool = VersionTool()
if version_tool.remove(get.sitename, get.version) is None:
return public.returnResult(True, '删除成功')
return json_response(False, '删除失败')
# 恢复版本
def recover_version(self, get):
try:
if not hasattr(get, 'sitename'):
return json_response(False, 'The project name cannot be empty')
if not hasattr(get, 'version'):
return json_response(False, '版本号不能为空')
project_data = self.get_project_find(get.sitename)
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.sitename))
version_tool = VersionTool()
project_config = project_data['project_config']
# spring jar 包情况
if project_config["java_type"] == "springboot":
v_info = version_tool.get_version_info(get.sitename, get.version)
if not v_info:
return json_response(False, 'The specified version does not exist: {}'.format(get.version))
path = os.path.join(version_tool.pack_path, v_info['zip_name'])
if not os.path.isfile:
return json_response(False, 'The specified version file is missing')
if os.path.exists(project_config["project_jar"] + "_back"):
os.remove(project_config["project_jar"] + "_back")
if not path.endswith(".jar"): # 如果不是jar包则解压并寻找jar包
output_dir = str(os.path.join('/tmp', public.GetRandomString(16)))
os.makedirs(output_dir, 777)
if not self.extract_archive(path, output_dir)[0]:
return json_response(False, '解压失败')
else:
for f in os.listdir(output_dir):
if f.endswith(".jar"):
path = os.path.join(output_dir, f)
break
else:
return json_response(False, '未找到jar包文件')
shutil.move(project_config["project_jar"], project_config["project_jar"] + "_back")
shutil.copyfile(path, project_config["project_jar"])
return json_response(True, "版本文件替换成功,重启后生效")
# war 包
v_info = version_tool.get_version_info(get.sitename, get.version)
if not v_info:
return json_response(False, 'The specified version does not exist: {}'.format(get.version))
path = os.path.join(version_tool.pack_path, v_info['zip_name'])
if path.endswith(".war") and os.path.isfile(project_data["path"]): # 如果是war包
if os.path.exists(project_data["path"] + "_back"):
os.remove(project_data["path"] + "_back")
shutil.move(project_data["path"], project_data["path"] + "_back")
shutil.copyfile(path, project_data["path"])
return json_response(True, "版本文件替换成功,重启后生效")
res = version_tool.recover(get.sitename, get.version, project_data['path'])
if res is not True:
return json_response(False, res)
return json_response(True, '恢复成功')
except:
return json_response(False, traceback.format_exc())
def now_file_backup(self, get):
try:
if not hasattr(get, 'sitename'):
return json_response(False, 'The project name cannot be empty')
if not hasattr(get, 'version') or not get.version.strip():
return json_response(False, '版本号不能为空')
else:
get.version = get.version.strip()
if not hasattr(get, 'ps'):
get.ps = ''
project_data = self.get_project_find(get.sitename)
if not project_data:
return json_response(False, 'The specified item does not exist: {}'.format(get.sitename))
path = project_data['path']
version_tool = VersionTool()
project_config = project_data['project_config']
if project_config["java_type"] == "springboot":
res = version_tool.publish_by_file(get.sitename, project_config["project_jar"], get.version, get.ps)
else:
if os.path.isdir(path):
res = version_tool.publish_by_src_path(get.sitename, path, get.version, get.ps, sync=True)
elif os.path.isfile(path):
res = version_tool.publish_by_file(get.sitename, path, get.version, get.ps)
else:
return json_response(False, '添加失败')
if res is None:
return json_response(True, '添加成功')
return json_response(False, '添加失败' + res)
except:
return json_response(False, traceback.format_exc())
@staticmethod
def set_version_ps(get):
if not hasattr(get, 'sitename'):
return json_response(False, 'The project name cannot be empty')
if not hasattr(get, 'version'):
return json_response(False, '版本号不能为空')
if not hasattr(get, 'ps'):
get.ps = ''
version_tool = VersionTool()
res = version_tool.set_ps(get.sitename, get.version, get.ps)
if not res:
return json_response(False, '设置失败')
return json_response(True, '设置成功')
def change_log_path(self, get):
""""修改日志文件地址
@author baozi <202-03-13>
@param:
get ( dict ): 请求: 包含项目名称和新的路径
@return
"""
try:
project_data = self.get_project_find(get.project_name.strip())
new_log_path = get.path.strip().rstrip("/")
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, 'The project does not exist')
if not new_log_path.startswith('/'):
return json_response(False, '路径格式错误')
if not os.path.exists(new_log_path):
os.makedirs(new_log_path, mode=0o777)
project_config = project_data["project_config"]
if project_config['java_type'] == 'springboot':
project_config['logs'] = new_log_path + '/' + project_data["name"] + '.log'
pdata = {
'name': project_data["name"],
'project_config': json.dumps(project_config)
}
public.M('sites').where('id=?', (project_data["id"],)).update(pdata)
# 重启项目
res = self.restart_project(get)
self.write_project_log('修改Java项目{}日志路径为:{}'.format(get.project_name, new_log_path))
return json_response(True, "项目日志路径修改成功")
elif project_config['java_type'] == 'duli':
project_config['logs'] = new_log_path + '/'
tomcat = utils.site_tomcat(project_data["name"])
if not tomcat.change_log_path(new_log_path, project_data["name"].replace(".", "_")):
return public.returnMsg(False, "项目日志路径修改失败")
pdata = {
'name': project_data["name"],
'project_config': json.dumps(project_config)
}
public.M('sites').where('name=?', (get.project_name.strip(),)).update(pdata)
# 重启项目
tomcat.restart()
self.write_project_log('修改Java项目{}日志路径为:{}'.format(get.project_name, new_log_path))
return json_response(True, "项目日志路径修改成功")
elif project_config['java_type'] == 'neizhi':
tomcat = utils.bt_tomcat(project_config['tomcat_version'])
if not tomcat.change_log_path(new_log_path, str(project_config['tomcat_version'])):
return public.returnMsg(False, "项目日志路径修改失败")
tomcat.restart()
self.write_project_log('修改Java项目{}日志路径为:{}'.format(get.project_name, new_log_path))
return json_response(True, "项目日志路径修改成功")
else:
return json_response(False, "项目类型错误")
def multi_remove_project(self, get):
"""
@name 批量删除项目
@author baozi<2023-3-2>
@param get<dict_obj>{
project_names: list[string] <项目名称>所组成的列表
}
@return dict
"""
try:
project_names = get.project_names
if isinstance(project_names, list):
project_names = [i.strip() for i in project_names]
else:
project_names = []
except:
return json_response(False, "Parameter error")
if not project_names:
return json_response(False, "未选中要删除的站点")
projects = public.M('sites').where(
'project_type=? AND name in ({})'.format(",".join(["?"] * len(project_names))),
('Java', *project_names)).select()
if not projects:
return public.returnMsg(False, "未选中要删除的站点")
_duli, _neizh, _springboot = [], [], []
for project in projects:
project['project_config'] = json.loads(project['project_config'])
if project['project_config']['java_type'] == 'duli':
_duli.append(project)
elif project['project_config']['java_type'] == 'neizhi':
_neizh.append(project)
elif project['project_config']['java_type'] == 'springboot':
_springboot.append(project)
# 执行每种删除的独特操作
if _duli:
self._multi_remove_duli(_duli)
if _neizh:
self._multi_remove_neizhi(_neizh)
if _springboot:
self._multi_remove_springboot(_springboot)
# 清除Nginx Apache 配置文件,并重起服务
for i in projects:
remove_sites_service_config(i["name"], config_prefix="java_")
# 从面板数据库删除信息
project_ids = tuple([i["id"] for i in projects])
public.M('domain').where('pid IN ({})'.format(",".join(["?"] * len(projects))), project_ids).delete()
public.M('sites').where('id IN ({})'.format(",".join(["?"] * len(project_ids))), project_ids).delete()
self.write_project_log('批量删除Java项目:[{}]'.format("; ".join([i["name"] for i in projects])))
for project in projects:
self.del_crontab(project["name"])
return json_response(True, "删除项目成功", data=[i["name"] for i in projects])
@staticmethod
def _multi_remove_duli(projects):
for project in projects:
# 关闭独立项目
tomcat = utils.site_tomcat(project["name"])
if tomcat:
tomcat.stop()
if os.path.exists(tomcat.path):
shutil.rmtree(tomcat.path)
@staticmethod
def _multi_remove_neizhi(projects):
used_tomcat: Dict[int, utils.TomCat] = {}
for project in projects:
ver = int(project['project_config']['tomcat_version'])
if ver in used_tomcat:
tomcat = used_tomcat[ver]
else:
tomcat = utils.bt_tomcat(ver)
if not tomcat:
continue
used_tomcat[ver] = tomcat
tomcat.remove_host(project["name"])
for t in used_tomcat.values():
t.save_config_xml()
t.restart()
def _multi_remove_springboot(self, projects):
for project in projects:
# 停止项目
server_name = "spring_" + project["name"] + project.get("server_name_suffix", "")
s_admin = RealServer()
s_admin.daemon_admin(server_name, "stop")
s_admin.del_daemon(server_name)
project_config = project["project_config"]
pid_file = project_config['pids']
if os.path.exists(pid_file):
os.remove(pid_file)
script_file = project_config['scripts']
if os.path.exists(script_file):
os.remove(script_file)
env_path = "{}/env/{}.env".format(self._java_project_vhost, project_config["project_name"])
if os.path.exists(env_path):
os.remove(env_path)
log_file = project_config['logs']
if os.path.exists(log_file):
os.remove(log_file)
def multi_set_project(self, get):
"""
@name 批量设置项目
@author baozi<2023-3-2>
@param get<dict_obj>{
project_names: list[string] <项目名称>所组成的列表
}
@return dict
"""
try:
project_names = get.project_names
set_type = get.operation.strip()
except:
return json_response(False, "Parameter error")
if set_type not in ["start", "stop"]:
return public.returnMsg(False, "操作信息错误")
if isinstance(project_names, list):
project_names = [i.strip() for i in project_names]
else:
project_names = []
projects = public.M('sites').where(
'project_type=? AND name in ({})'.format(",".join(["?"] * len(project_names))),
('Java', *project_names)
).select()
if not projects:
return json_response(False, "未选中要启动的站点")
project_names = [i["name"] for i in projects]
spring_boot_projects = []
duli_tomcat = []
bt_tomcat = {}
error_list = []
for project in projects:
project['project_config'] = json.loads(project['project_config'])
if project['project_config']['java_type'] == 'neizhi':
ver = int(project['project_config']['tomcat_version'])
if ver not in bt_tomcat:
tomcat = utils.bt_tomcat(project['project_config']['tomcat_version'])
if not tomcat:
error_list.append({"project_name": project["name"], "msg": "启动失败,没有安装Tomcat{}".format(
project['project_config']['tomcat_version'])})
project_names.remove(project["name"])
continue
bt_tomcat[ver] = tomcat
if project['project_config']['java_type'] == 'duli':
tomcat = utils.site_tomcat(project["name"])
if tomcat:
duli_tomcat.append(tomcat)
if project['project_config']['java_type'] == 'springboot':
spring_boot_projects.append(project)
for t in itertools.chain(bt_tomcat.values(), duli_tomcat):
if set_type == "start":
t.start()
else:
t.stop()
for i in spring_boot_projects:
if set_type == "start":
self.start_project(public.to_dict_obj({"project_name": i["name"]}))
else:
self.stop_project(public.to_dict_obj({"project_name": i["name"]}))
if error_list:
return json_response(True, msg="部分项目操作失败", data={
"error_list": error_list,
"project_names": project_names
})
return json_response(True, msg="启动成功" if set_type == "start" else "停止成功", data={
"project_names": project_names
})
@staticmethod
def del_crontab(project_name: str):
"""
@name 删除项目日志切割任务
@auther hezhihong<2022-10-31>
@return
"""
cron_name = '[勿删]Java项目[{}]运行日志切割'.format(project_name)
cron_path = public.GetConfigValue('setup_path') + '/cron/'
cron_list = public.M('crontab').where("name=?", (cron_name,)).select()
if cron_list:
for i in cron_list:
if not i: continue
cron_echo = public.M('crontab').where("id=?", (i['id'],)).getField('echo')
args = {"id": i['id']}
import crontab
crontab.crontab().DelCrontab(args)
del_cron_file = cron_path + cron_echo
public.ExecShell("crontab -u root -l| grep -v '{}'|crontab -u root -".format(del_cron_file))
def get_load_info(self, get):
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, "未找到项目")
pid = self.get_project_pid(project_data)
if not pid:
return json_response(False, "项目未启动")
res = self.real_process.get_process_tree(pid)
if isinstance(res["data"], list):
res["data"] = {i.get("pid", "0"): i for i in res["data"]}
return res
def get_port_status(self, get):
try:
project_data = self.get_project_find(get.project_name.strip())
except:
return json_response(False, '参数错误')
if not project_data:
return json_response(False, "未找到项目")
pid = self.get_project_pid(project_data)
if not pid:
return json_response(False, "项目未启动")
ports = []
try:
p = psutil.Process(pid)
for i in p.connections():
if i.status == "LISTEN" and i.laddr.port not in ports:
ports.append(str(i.laddr.port))
except:
pass
if not ports:
return json_response(False, "未找到端口")
res = {str(i): {
"port": i,
"fire_wall": None,
"nginx_proxy": None,
} for i in ports}
from firewallModelV2.comModel import main
port_list = main().port_rules_list(get)['message']
for i in port_list:
if str(i["Port"]) in res:
res[str(i["Port"])]['fire_wall'] = i
rsp = RealServerProxy(project_data)
proxy_list = rsp.get_proxy_list()
for i in proxy_list:
if str(i["proxy_port"]) in res:
res[str(i["proxy_port"])]['nginx_proxy'] = i
return json_response(True, "获取成功", data=list(res.values()))
def add_server_proxy(self, get):
if not hasattr(get, "site_name") or not get.site_name.strip():
return json_response(status=False, msg="Parameter error")
project_data = self.get_project_find(get.site_name)
if not project_data:
return json_response(False, "未找到项目")
rp = RealServerProxy(project_data)
proxy_data = rp.check_args(get, is_modify=False)
if isinstance(proxy_data, str):
return json_response(status=False, msg=proxy_data)
# 使用正则匹配尝试添加
res = rp.create_proxy(proxy_data)
if res is None:
return json_response(status=True, msg="添加成功")
# 尝试模板生成
proxy_info = project_data['project_config'].get("proxy_info", [])
proxy_info.append(proxy_data)
project_data['project_config']['proxy_info'] = proxy_info
domain_list = self._project_domain_list(project_data['id'])
domains = [(i["name"], str(i["port"])) for i in domain_list]
ssl, f_ssl = self._get_ssl_status(project_data['name'])
error_msg = self.create_config(project_data, domains, ssl, f_ssl)
if not error_msg:
public.serviceReload()
pdata = {
'project_config': json.dumps(project_data['project_config'])
}
public.M("sites").where("id=?", (project_data['id'],)).update(pdata)
return json_response(status=True, msg="添加成功")
return json_response(status=False, msg=error_msg)
def modify_server_proxy(self, get):
if not hasattr(get, "site_name") or not get.site_name.strip():
return json_response(status=False, msg="Parameter error")
project_data = self.get_project_find(get.site_name)
if not project_data:
return json_response(False, "未找到项目")
rp = RealServerProxy(project_data)
proxy_data = rp.check_args(get, is_modify=True)
if isinstance(proxy_data, str):
return json_response(status=False, msg=proxy_data)
proxy_info = project_data['project_config'].get("proxy_info", [])
idx = None
for index, i in enumerate(proxy_info):
if i["proxy_id"] == proxy_data["proxy_id"] and i["site_name"] == proxy_data["site_name"]:
idx = index
break
if idx is None:
return json_response(status=False, msg="未找到该id的反向代理配置")
# 使用正则匹配尝试添加
res = rp.modify_proxy(proxy_data)
if res is None:
return json_response(status=True, msg="修改成功")
# 尝试模板生成
proxy_info[idx] = proxy_data
project_data['project_config']['proxy_info'] = proxy_info
domain_list = self._project_domain_list(project_data['id'])
domains = [(i["name"], str(i["port"])) for i in domain_list]
ssl, f_ssl = self._get_ssl_status(project_data['name'])
error_msg = self.create_config(proxy_data, domains, ssl, f_ssl)
if not error_msg:
public.serviceReload()
pdata = {
'project_config': json.dumps(project_data['project_config'])
}
public.M("sites").where("id=?", (project_data['id'],)).update(pdata)
return json_response(status=True, msg="修改成功")
return json_response(status=False, msg=error_msg)
def remove_server_proxy(self, get):
try:
site_name = get.site_name.strip()
proxy_id = get.proxy_id.strip()
except:
return json_response(status=False, msg="Parameter error")
project_data = self.get_project_find(site_name)
if not project_data:
return json_response(False, "未找到项目")
rp = RealServerProxy(project_data)
msg = rp.remove_proxy(site_name, proxy_id)
if msg:
return json_response(status=False, msg=msg)
return json_response(status=True, msg="Successfully delete")
def server_proxy_list(self, get):
try:
site_name = get.site_name.strip()
except:
return json_response(status=False, msg="Parameter error")
project_data = self.get_project_find(site_name)
if not project_data:
return json_response(False, "未找到项目")
_p = RealServerProxy(project_data)
data = _p.get_proxy_list()
return json_response(status=True, data=data)
@staticmethod
def check_env_for_project(get):
project_cmd = ""
by_process = 0
env_list = []
env_file = ''
try:
if hasattr(get, "project_cmd") and get.project_cmd:
project_cmd = get.project_cmd.strip()
project_jar = get.project_jar.strip()
if hasattr(get, "by_process") and get.by_process:
by_process = int(get.by_process)
if hasattr(get, "env_list") and get.env_list:
env_list = get.env_list
if hasattr(get, "env_file") and get.env_file:
env_file = get.env_file
except:
return json_response(status=False, msg="Parameter error")
if not os.path.exists(project_jar):
return json_response(status=False, msg="jar文件不存在")
if env_file and not os.path.exists(env_file):
return json_response(status=False, msg="环境变量文件不存在")
spring_parser = SpringConfigParser(
jar_path=project_jar,
process=by_process,
cmd=project_cmd,
env_list=env_list,
env_file=env_file,
)
data = spring_parser.get_tip()
if not data:
return json_response(status=True, msg="未检测到配置问题", data=data)
return json_response(status=True, data=data)
def set_static_path(self, get):
try:
project_name = get.project_name.strip()
project_data = self.get_project_find(project_name)
status = utils.js_value_to_bool(get.status)
index = get.index.strip()
path = get.path.strip()
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目无法设置静态文件")
proxy_info = project_data['project_config'].get("proxy_info", [])
for i in proxy_info:
if i["proxy_dir"] == "/":
return json_response(status=False, msg="项目已存在根路由【/】配置,无法设置态文件配置")
project_data["project_config"]["static_info"] = {
"status": status,
"index": index,
"path": path,
"use_try_file": True,
}
res = self._set_static_path(project_data)
if isinstance(res, str):
return json_response(status=False, msg=res)
public.M("sites").where("id=?", (project_data["id"],)).update({
"project_config": json.dumps(project_data["project_config"])
})
return json_response(status=True, msg="Successfully set")
def get_keep_status(self, get):
try:
project_name = get.project_name.strip()
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
from mod.project.java.project_update import ProjectUpdate
if not project_data:
return json_response(False, "未找到项目")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目不支持该功能")
p = ProjectUpdate(project_name, project_data["project_config"]["project_jar"])
res = p.get_keep_status()
return res
def update_project_by_restart(self, get):
try:
project_name = get.project_name.strip()
project_jar = get.project_jar.strip()
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目不支持该功能")
from mod.project.java.project_update import ProjectUpdate
p = ProjectUpdate(project_name, new_jar=project_jar)
res = p.restart_update()
return res
def update_project_by_keep(self, get):
now_port = 0
run_time = 0
try:
project_name = get.project_name.strip()
project_jar = get.project_jar.strip()
if hasattr(get, "now_port") and get.now_port:
now_port = int(get.now_port)
if hasattr(get, "run_time") and get.run_time:
run_time = int(get.run_time)
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目不支持该功能")
if not os.path.isfile(project_jar):
return json_response(status=False, msg="jar文件不存在")
if public.get_webserver() != "nginx":
return json_response(status=False, msg="当前只支持nginx使用")
ng_file = "/www/server/panel/vhost/nginx/java_{}.conf".format(project_name)
if not os.path.exists(ng_file):
return json_response(status=False, msg="未启用外网访问的不能进行不停机更新")
panel_path = "/www/server/panel"
pid_file = "{}/keep/{}.pid".format(self._java_project_path, project_name)
public.ExecShell(
"nohup {}/pyenv/bin/python3 {}/mod/project/java/project_update.py {} {} {} {} &> /dev/null & \n"
"echo $! > {} ".format(
panel_path, panel_path, project_name, project_jar, now_port, run_time, pid_file)
)
return json_response(status=True, msg="更新任务已开始")
def force_stop(self, get):
try:
project_name = get.project_name.strip()
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
project_config = project_data["project_config"]
pid_file = "{}/keep/{}.pid".format(self._java_project_path, project_name)
pid_data = public.readFile(pid_file)
if isinstance(pid_data, str) and pid_data != "0":
try:
p = psutil.Process(int(pid_data))
p.kill()
except:
pass
service_list = []
rep_service = re.compile(r"^spring_%s_\S{8}$" % public.prevent_re_key(project_name), re.M)
for i in os.scandir("/usr/lib/systemd/system"):
if i.is_file() and rep_service.match(i.name):
service_list.append(i.name)
now_name = "spring_" + project_config["project_name"] + "_" + project_config.get("server_name_suffix", "")
if now_name in service_list:
service_list.remove(now_name)
for i in service_list:
public.ExecShell("systemctl stop {}".format(i))
os.remove("/usr/lib/systemd/system/{}".format(i))
public.ExecShell("systemctl daemon-reload")
upstream_file = "/www/server/panel/vhost/nginx/java_{}_upstream.conf".format(project_name)
if os.path.isfile(upstream_file): # 说明新旧同时存在 则删除旧的
upstream_data = public.readFile(upstream_file)
if isinstance(upstream_data, str):
old_upstream_data = re.search(r"server 127\.0\.0\.1:(?P<port>\d+);", upstream_data)
if old_upstream_data:
old_port = old_upstream_data.group("port")
ng_file = "/www/server/panel/vhost/nginx/java_{}.conf".format(project_name)
ng_data = public.readFile(ng_file)
if not isinstance(ng_data, str):
return "Nginx配置文件读取错误无法取消轮询使用新实例"
new_config = ng_data.replace("{}_backend".format(project_name), "127.0.0.1:{}".format(old_port))
public.writeFile(ng_file, new_config)
res = public.checkWebConfig()
if res is not True:
public.writeFile(ng_file, ng_data)
else:
os.remove(upstream_file)
public.serviceReload()
return json_response(status=True, msg="强制停止成功")
def keep_option(self, get):
try:
project_name = get.project_name.strip()
option = get.option.strip()
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
if option not in ("use_new", "use_old", "stop_new"):
return json_response(status=False, msg="Parameter error")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目不支持该功能")
from mod.project.java.project_update import ProjectUpdate
p = ProjectUpdate(project_name, project_data["project_config"]["project_jar"])
res = p.keep_option(option)
return res
def get_spring_log_list(self, get):
try:
project_name = get.project_name.strip()
project_data = self.get_project_find(project_name)
except:
return json_response(status=False, msg="Parameter error")
if not project_data:
return json_response(False, "未找到项目")
if not project_data["project_config"]["java_type"] == "springboot":
return json_response(status=False, msg="非springboot项目不支持该功能")
pid = self.get_project_pid(project_data)
project_config = project_data["project_config"]
project_jar = project_config["project_jar"]
project_cmd = project_config["project_cmd"]
env_list = project_config["env_list"]
env_file = project_config["env_file"]
spring_log_parser = SpringLogConfigParser(
jar_path=project_jar,
process=pid,
cmd=project_cmd,
env_list=env_list,
env_file=env_file,
)
res = []
for i in spring_log_parser.get_all_log_ptah():
for j in os.scandir(i):
if j.is_file() and j.name.endswith(".log"):
log_path = os.path.join(i, j.name)
res.append(log_path)
return json_response(status=True, data=res)
@staticmethod
def get_spring_log_data(get):
try:
log_file = get.log_file.strip()
except:
return json_response(status=False, msg="Parameter error")
if not os.path.isfile(log_file):
return json_response(status=False, msg="日志文件不存在")
return json_response(status=True, data=public.GetNumLines(log_file, 1000))
@staticmethod
def install_jdk_new(get):
if not hasattr(get, 'version') or not get.version.strip():
return json_response(False, '版本号不能为空')
version = get.version.strip()
if os.path.exists('/www/server/java/' + version):
return json_response(False, '版本已经存在')
jdk_manager = utils.JDKManager()
if version not in jdk_manager.versions_list:
return public.returnMsg(False, '版本号不存在')
jdk_manager.async_install_jdk(version)
return json_response(True, '已添加到安装任务,请在消息盒子中查看安装情况')
@staticmethod
def install_tomcat_new(get):
java_path = None
if not hasattr(get, 'version') or not get.version.strip():
return json_response(False, '版本号不能为空')
version = get.version.strip()
if hasattr(get, 'java_path') and get.java_path.strip():
java_path = get.java_path.strip()
res = utils.TomCat.async_install_tomcat_new(version, java_path)
if res is not None:
return json_response(False, res)
return json_response(True, '已添加到安装任务,请在消息盒子中查看安装情况')