Files
tra-app/devops/iso/新的/ipa_server.py
T
2025-11-10 10:00:46 +08:00

101 lines
3.8 KiB
Python

#!/opt/miniconda3/bin/python3
import os
import sys
import socket
import http.server
import socketserver
import subprocess
from urllib.parse import urlparse
# 配置基础路径和端口(推荐使用 1024-65535 之间的端口,避免系统预留端口)
BUILD_DIR = os.path.join(os.path.expanduser('~'), 'Desktop', 'lx_uniapp', 'build')
DEFAULT_PORT = 8000 # 若仍失败,可改为 8080、9000 等
def check_port_available(port):
"""检查端口是否真的可用(比 lsof 更可靠)"""
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
try:
s.bind(("", port)) # 尝试绑定端口,成功则可用
return True
except OSError:
return False
def free_port(port):
"""释放占用端口的进程"""
try:
result = subprocess.check_output(
f"lsof -i :{port} | grep LISTEN | awk '{{print $2}}'",
shell=True,
text=True,
stderr=subprocess.STDOUT # 忽略错误输出
)
pids = [pid.strip() for pid in result.split('\n') if pid.strip()]
if pids:
print(f"释放端口 {port} 占用的进程:{pids}")
for pid in pids:
subprocess.run(f"kill -9 {pid}", shell=True, check=True)
except subprocess.CalledProcessError:
pass # 无进程占用时正常
except Exception as e:
print(f"释放端口警告:{e}(可忽略)")
class IPARequestHandler(http.server.SimpleHTTPRequestHandler):
# 省略与之前相同的 do_GET 实现(保持不变)
def do_GET(self):
parsed_path = urlparse(self.path)
target_branch = parsed_path.path.strip('/')
if not target_branch:
self.send_response(400)
self.end_headers()
self.wfile.write("请指定分支名,例如: http://服务器IP:端口/sit".encode('utf-8'))
return
ipa_dir_name = f"{target_branch}_ipa_production"
ipa_path = os.path.join(BUILD_DIR, ipa_dir_name, "HBuilder.ipa")
if not os.path.exists(ipa_path):
self.send_response(404)
self.end_headers()
self.wfile.write(f"文件不存在: {ipa_path}".encode('utf-8'))
return
self.send_response(200)
self.send_header('Content-Type', 'application/octet-stream')
self.send_header('Content-Disposition', f'attachment; filename="HBuilder_{target_branch}.ipa"')
self.end_headers()
with open(ipa_path, 'rb') as f:
self.wfile.write(f.read())
if __name__ == '__main__':
# 1. 先尝试释放端口
free_port(DEFAULT_PORT)
# 2. 检查端口是否真的可用
if not check_port_available(DEFAULT_PORT):
print(f"端口 {DEFAULT_PORT} 仍被占用,尝试自动切换端口...")
# 自动切换到 8080 端口(若 8000 不可用)
DEFAULT_PORT = 8080
free_port(DEFAULT_PORT)
if not check_port_available(DEFAULT_PORT):
print(f"端口 {DEFAULT_PORT} 也被占用,请手动指定其他端口(如 9000)")
sys.exit(1)
# 3. 启动服务(增加错误捕获)
try:
# 禁用地址重用限制(解决 TIME_WAIT 状态导致的启动失败)
socketserver.TCPServer.allow_reuse_address = True
with socketserver.TCPServer(("", DEFAULT_PORT), IPARequestHandler) as httpd:
print(f"\nIPA 文件服务已启动,端口: {DEFAULT_PORT}")
print(f"访问格式: http://服务器IP:{DEFAULT_PORT}/目标分支名")
print(f"示例: http://25.64.32.152:{DEFAULT_PORT}/sit")
httpd.serve_forever()
except Exception as e:
print(f"服务启动失败:{str(e)}")
print("可能原因:权限不足(尝试非 1-1024 端口)或网络配置限制")
sys.exit(1)