调通了第一个版本,可以运行。

This commit is contained in:
chenxudong 2025-06-04 17:27:37 +08:00
commit 497a2ebaf5
7 changed files with 762 additions and 0 deletions

2
build.txt Normal file
View File

@ -0,0 +1,2 @@
pyinstaller --onefile --add-data "datas/mariadb.zip:datas" --add-data "datas/init.sql:datas" --add-data "datas/jdk.zip:datas" src/install.py
pyinstaller --onefile --add-data "datas/electromagnetic.jar:datas" src/start.py

BIN
datas/electromagnetic.jar Normal file

Binary file not shown.

571
datas/init.sql Normal file

File diff suppressed because one or more lines are too long

BIN
datas/jdk.zip Normal file

Binary file not shown.

BIN
datas/mariadb.zip Normal file

Binary file not shown.

117
src/install.py Normal file
View File

@ -0,0 +1,117 @@
import os
import sys
import zipfile
import subprocess
import loguru
# from loguru import logger
import shutil
import psutil
path = r'D:\database'
service_name = 'ComacMariaDB'
passowrd = '1qaz@WSX'
mariadb_data_path = r'D:\database\mariadb\data'
init_sql = r'D:/database/mariadb/data/init.sql'
mariadb_port = 3417
init_schema = 'em_data_prod'
def ensure_dir(directory):
if not os.path.exists(directory):
os.makedirs(directory)
loguru.logger.info(f"目录 {directory} 已创建")
else:
loguru.logger.info(f"目录 {directory} 已存在")
def unzip_file():
new_path = get_resource_path(os.path.join('datas', 'mariadb.zip'))
with zipfile.ZipFile(new_path, 'r') as zip_ref:
zip_ref.extractall(path) # 将文件解压到指定路径
def register_service():
args1 = path + '/mariadb/bin/mysql_install_db.exe'
args2 = '--datadir=' + mariadb_data_path
args3 = '--service=' + service_name
args4 = '--password=' + passowrd
args5 = '--port=' + str(mariadb_port)
res = subprocess.run([args1, args2, args3, args4, args5], text=True, capture_output=True)
loguru.logger.info(res.stdout)
return res
def start_mariadb():
command = 'net start ' + service_name
with os.popen(command) as stream:
res = stream.read()
loguru.logger.info(res)
def init_db():
command2 = fr'{path}\mariadb\bin\mysql --no-defaults -u root -p{passowrd} -P {mariadb_port} {init_schema} < {init_sql}'
with os.popen(command2) as stream:
res2 = stream.read()
loguru.logger.info(res2)
os.remove(init_sql)
pass
def init_db_user():
new_path = get_resource_path(os.path.join('datas', 'init.sql'))
shutil.copy(str(new_path), mariadb_data_path)
command1 = fr'{path}\mariadb\bin\mysql -u root -p{passowrd} -P {mariadb_port} -e "create database if not exists {init_schema}; use {init_schema};"'
with os.popen(command1) as stream:
res = stream.read()
loguru.logger.info(res)
def check_service(service_name):
"""检查服务是否存在及运行状态"""
try:
service = psutil.win_service_get(service_name)
service_info = service.as_dict()
if service_info['status'] == 'running':
loguru.logger.info(f"服务 {service_name} 正在运行")
return True
else:
loguru.logger.info(f"服务 {service_name} 已停止,正在尝试启动...")
start_mariadb()
return True
except psutil.NoSuchProcess:
loguru.logger.info(f"服务 {service_name} 不存在")
return False
except Exception as e:
loguru.logger.info(f"检测服务时出错: {str(e)}")
return False
def get_resource_path(relative_path):
""" 获取资源绝对路径适用于开发环境和PyInstaller打包后 """
if hasattr(sys, '_MEIPASS'):
# 打包后的资源路径sys._MEIPASS + 相对路径
base_path = sys._MEIPASS
else:
# 开发环境的基础路径
base_path = os.path.abspath(".")
return os.path.join(base_path, relative_path)
def set_java_env():
new_path = get_resource_path(os.path.join('datas', 'jdk.zip'))
with zipfile.ZipFile(str(new_path), 'r') as zip_ref:
zip_ref.extractall(path) # 将文件解压到指定路径
pass
def start_install():
status = check_service(service_name)
if status:
return
loguru.logger.info("开始安装MariaDB")
ensure_dir(path)
loguru.logger.info("开始解压文件")
unzip_file()
loguru.logger.info("开始注册服务")
register_service()
loguru.logger.info("启动数据库")
start_mariadb()
loguru.logger.info("数据库用户初始化")
init_db_user()
loguru.logger.info("数据库初始化")
init_db()
loguru.logger.info("设置Java运行环境")
set_java_env()
if __name__ == '__main__':
start_install()

72
src/start.py Normal file
View File

@ -0,0 +1,72 @@
import os
from loguru import logger
import subprocess
import sys
from datetime import datetime
import re
# 获取当前脚本所在的目录
new_java_path = 'D:/database/jdk/bin/java.exe'
def get_resource_path(relative_path):
""" 获取资源绝对路径适用于开发环境和PyInstaller打包后 """
if hasattr(sys, '_MEIPASS'):
# 打包后的资源路径sys._MEIPASS + 相对路径
base_path = sys._MEIPASS
else:
# 开发环境的基础路径
base_path = os.path.dirname(os.path.abspath("."))
return os.path.join(base_path, relative_path)
# 构建JDK和JAR的路径
jar_path = os.path.join("datas", "electromagnetic.jar")
def start():
try:
new_jar_path = get_resource_path(jar_path)
java_command = [new_java_path, "-jar", new_jar_path]
# 创建新进程组支持Unix/Windows的进程隔离
creation_flags = subprocess.CREATE_NEW_PROCESS_GROUP
# 重定向输出到日志文件
formatted_time = datetime.now().strftime("%Y%m%d%H%M%S")
log_file = rf'D:\database\app_{formatted_time}.log'
with open(log_file, "a") as log:
process = subprocess.Popen(
java_command,
stdout=log,
stderr=log,
start_new_session=True, # 创建新会话
creationflags=creation_flags
)
logger.info(f"Spring Boot 应用已在后台启动! PID: {process.pid}")
logger.info(f"日志输出: {os.path.abspath(log_file)}")
except Exception as e:
logger.info(f"启动失败: {str(e)}")
sys.exit(1)
def kill_process_by_port(port):
# 执行netstat命令获取端口占用信息
cmd_netstat = ['netstat', '-ano', '-p', 'tcp']
result = subprocess.run(cmd_netstat, capture_output=True, text=True, shell=True)
# 在输出中查找指定端口
pid = None
pattern = fr':{port}\s+.*LISTENING\s+(\d+)'
match = re.search(pattern, result.stdout)
if match:
pid = match.group(1)
# 如果找到PID则终止进程
if pid:
try:
subprocess.run(['taskkill', '/F', '/PID', pid], check=True)
logger.info(f"已终止占用端口 {port} 的进程 (PID: {pid})")
except subprocess.CalledProcessError:
logger.info(f"终止进程 {pid} 失败 (可能权限不足或进程不存在)")
else:
logger.info(f"端口 {port} 未被占用")
if __name__ == '__main__':
kill_process_by_port(12396)
# start()