Files
server_manager/src/services/commands/erlang.py
T
2026-05-22 00:16:08 +08:00

147 lines
4.5 KiB
Python
Raw 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.
# -*- coding: utf-8 -*-
"""Erlang and build-tool command resolution."""
from .shared import *
def get_erl_cmd(erl_path: str = None) -> str:
"""根据配置路径获取 erl 可执行文件路径
Args:
erl_path: Erlang 安装根目录(如 E:/app/erlang/Erlang_OTP_25
Returns:
erl 可执行文件的完整路径,或默认的 'erl'
"""
if erl_path and erl_path.strip():
if IS_WINDOWS:
erl_exe = Path(erl_path.strip()) / 'bin' / 'erl.exe'
if erl_exe.exists():
return str(erl_exe)
else:
erl_bin = Path(erl_path.strip()) / 'bin' / 'erl'
if erl_bin.exists():
return str(erl_bin)
return 'erl'
def subprocess_args_to_display(args: List[str]) -> str:
"""将 subprocess 参数列表转为可读的命令字符串(仅用于显示/日志)"""
parts = []
for a in args:
if ' ' in a or '"' in a or "'" in a or any(c in a for c in '()[]{}&|<>^'):
parts.append(f'"{a}"')
else:
parts.append(a)
return ' '.join(parts)
def get_escript_cmd(erl_path: str = None) -> str:
"""根据配置路径获取 escript 可执行文件路径
Args:
erl_path: Erlang 安装根目录
Returns:
escript 可执行文件的完整路径,或默认的 'escript'
"""
if erl_path and erl_path.strip():
if IS_WINDOWS:
escript_exe = Path(erl_path.strip()) / 'bin' / 'escript.exe'
if escript_exe.exists():
return str(escript_exe)
else:
escript_bin = Path(erl_path.strip()) / 'bin' / 'escript'
if escript_bin.exists():
return str(escript_bin)
return 'escript'
def _ensure_epmd_daemon(erl_path: Optional[str] = None) -> None:
"""尽量执行 epmd -daemon。本机已有 epmd 时通常无害(就绪则不再重复监听)。"""
erl_exe = Path(get_erl_cmd(erl_path))
epmd = erl_exe.parent / ("epmd.exe" if IS_WINDOWS else "epmd")
if not epmd.is_file():
which = shutil.which("epmd")
if not which:
return
epmd = Path(which)
try:
subprocess.run(
[str(epmd), "-daemon"],
capture_output=True,
timeout=5,
creationflags=getattr(subprocess, "CREATE_NO_WINDOW", 0) if IS_WINDOWS else 0,
)
except Exception:
pass
def get_rebar3_cmd(server_root: str, erl_path: str = None) -> str:
"""获取 rebar3 执行命令
如果配置了 erl_path,直接用配置路径的 escript 来运行 rebar3 脚本,
而不是依赖系统 PATH 中的 escript。
Args:
server_root: 服务器根目录(rebar3 脚本所在目录)
erl_path: Erlang 安装根目录
Returns:
rebar3 执行命令字符串
"""
escript = get_escript_cmd(erl_path)
if IS_WINDOWS:
rebar3_script = Path(server_root) / 'rebar3'
if escript != 'escript':
return f'"{escript}" "{rebar3_script}"'
return REBAR3_CMD
else:
rebar3_script = Path(server_root) / 'rebar3'
if escript != 'escript':
return f'"{escript}" "{rebar3_script}"'
return './rebar3'
def get_local_ip() -> str:
"""获取本机IP地址"""
try:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()
return ip
except:
return "127.0.0.1"
def get_ebin_paths(server_root: str, profile: str = 'game_server_dev') -> List[str]:
"""获取所有 ebin 目录路径
Args:
server_root: 服务器根目录
profile: rebar3 profile 名称 (game_server_dev/login_server_dev/client_server_dev)
Returns:
ebin 目录路径列表
"""
ebin_paths = []
build_dir = Path(server_root) / "_build" / profile / "lib"
if build_dir.exists():
for app_dir in build_dir.iterdir():
if app_dir.is_dir():
ebin_dir = app_dir / "ebin"
if ebin_dir.exists():
ebin_paths.append(str(ebin_dir))
# 添加 checkouts 目录
checkouts_dir = Path(server_root) / "_build" / profile / "checkouts"
if checkouts_dir.exists():
for app_dir in checkouts_dir.iterdir():
if app_dir.is_dir():
ebin_dir = app_dir / "ebin"
if ebin_dir.exists():
ebin_paths.append(str(ebin_dir))
return ebin_paths