311 lines
12 KiB
Python
311 lines
12 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Cursor自动化服务统一启动脚本
|
||
- 检查数据库标记
|
||
- 启动自动化服务或独立功能
|
||
- 集中管理各项服务功能
|
||
"""
|
||
import asyncio
|
||
import sys
|
||
import os
|
||
import argparse
|
||
import subprocess
|
||
import time
|
||
from typing import Optional, List
|
||
|
||
from loguru import logger
|
||
|
||
# Windows平台特殊处理,强制使用SelectorEventLoop
|
||
if sys.platform.startswith("win"):
|
||
asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy())
|
||
|
||
from core.config import Config
|
||
from core.database import DatabaseManager
|
||
|
||
|
||
# 配置日志
|
||
logger.remove()
|
||
logger.add(sys.stderr, level="INFO")
|
||
logger.add(
|
||
"start.log",
|
||
rotation="10 MB",
|
||
retention="10 days",
|
||
level="DEBUG",
|
||
compression="zip"
|
||
)
|
||
|
||
|
||
class CursorServiceManager:
|
||
def __init__(self):
|
||
self.config = Config.from_yaml()
|
||
self.db_manager = DatabaseManager(self.config)
|
||
self.service_process = None
|
||
self.upload_process = None
|
||
|
||
async def initialize(self):
|
||
"""初始化数据库连接"""
|
||
logger.info("初始化数据库连接")
|
||
await self.db_manager.initialize()
|
||
|
||
async def cleanup(self):
|
||
"""清理资源"""
|
||
logger.info("清理资源")
|
||
if self.service_process and self.service_process.poll() is None:
|
||
logger.info("终止自动化服务进程")
|
||
try:
|
||
if sys.platform.startswith("win"):
|
||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(self.service_process.pid)])
|
||
else:
|
||
self.service_process.terminate()
|
||
self.service_process.wait(timeout=5)
|
||
except Exception as e:
|
||
logger.error(f"终止进程时出错: {e}")
|
||
|
||
if self.upload_process and self.upload_process.poll() is None:
|
||
logger.info("终止上传进程")
|
||
try:
|
||
if sys.platform.startswith("win"):
|
||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(self.upload_process.pid)])
|
||
else:
|
||
self.upload_process.terminate()
|
||
self.upload_process.wait(timeout=5)
|
||
except Exception as e:
|
||
logger.error(f"终止进程时出错: {e}")
|
||
|
||
await self.db_manager.cleanup()
|
||
|
||
async def check_service_flag(self) -> bool:
|
||
"""检查数据库中是否存在启动标记"""
|
||
try:
|
||
# 创建系统设置表(如果不存在)
|
||
await self.db_manager.execute("""
|
||
CREATE TABLE IF NOT EXISTS system_settings (
|
||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||
key_name VARCHAR(50) UNIQUE NOT NULL,
|
||
value TEXT,
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||
)
|
||
""")
|
||
|
||
# 检查是否存在自动服务启动标记
|
||
result = await self.db_manager.fetch_one(
|
||
"SELECT value FROM system_settings WHERE key_name = 'auto_service_enabled'"
|
||
)
|
||
|
||
if result:
|
||
return result['value'] == '1'
|
||
else:
|
||
# 如果不存在记录,创建默认记录(不启用)
|
||
await self.db_manager.execute(
|
||
"INSERT INTO system_settings (key_name, value) VALUES ('auto_service_enabled', '0')"
|
||
)
|
||
return False
|
||
|
||
except Exception as e:
|
||
logger.error(f"检查服务标记时出错: {e}")
|
||
return False
|
||
|
||
async def set_service_flag(self, enabled: bool):
|
||
"""设置服务启动标记"""
|
||
try:
|
||
value = '1' if enabled else '0'
|
||
await self.db_manager.execute(
|
||
"INSERT INTO system_settings (key_name, value) VALUES ('auto_service_enabled', %s) "
|
||
"ON DUPLICATE KEY UPDATE value = %s",
|
||
(value, value)
|
||
)
|
||
logger.success(f"自动服务标记已{'启用' if enabled else '禁用'}")
|
||
except Exception as e:
|
||
logger.error(f"设置服务标记时出错: {e}")
|
||
|
||
def start_auto_service(self):
|
||
"""启动自动化服务"""
|
||
if self.service_process and self.service_process.poll() is None:
|
||
logger.info("自动化服务已在运行中")
|
||
return
|
||
|
||
logger.info("启动自动化服务")
|
||
try:
|
||
if sys.platform.startswith("win"):
|
||
self.service_process = subprocess.Popen(
|
||
["python", "auto_cursor_service.py"],
|
||
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
|
||
)
|
||
else:
|
||
self.service_process = subprocess.Popen(
|
||
["python3", "auto_cursor_service.py"]
|
||
)
|
||
|
||
logger.info(f"自动化服务已启动,PID: {self.service_process.pid}")
|
||
except Exception as e:
|
||
logger.error(f"启动自动化服务时出错: {e}")
|
||
self.service_process = None
|
||
|
||
def stop_auto_service(self):
|
||
"""停止自动化服务"""
|
||
if not self.service_process or self.service_process.poll() is not None:
|
||
logger.info("自动化服务未在运行")
|
||
self.service_process = None
|
||
return
|
||
|
||
logger.info("停止自动化服务")
|
||
try:
|
||
if sys.platform.startswith("win"):
|
||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(self.service_process.pid)])
|
||
else:
|
||
self.service_process.terminate()
|
||
self.service_process.wait(timeout=5)
|
||
|
||
logger.info("自动化服务已停止")
|
||
except Exception as e:
|
||
logger.error(f"停止自动化服务时出错: {e}")
|
||
|
||
self.service_process = None
|
||
|
||
def start_upload(self):
|
||
"""启动账号上传"""
|
||
logger.info("开始上传账号")
|
||
try:
|
||
if sys.platform.startswith("win"):
|
||
self.upload_process = subprocess.Popen(
|
||
["python", "upload_account.py"],
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE,
|
||
creationflags=subprocess.CREATE_NO_WINDOW
|
||
)
|
||
else:
|
||
self.upload_process = subprocess.Popen(
|
||
["python3", "upload_account.py"],
|
||
stdout=subprocess.PIPE,
|
||
stderr=subprocess.PIPE
|
||
)
|
||
|
||
# 等待进程完成
|
||
stdout, stderr = self.upload_process.communicate()
|
||
|
||
if self.upload_process.returncode != 0:
|
||
logger.error(f"上传账号进程异常终止,退出码: {self.upload_process.returncode}")
|
||
if stderr:
|
||
logger.error(f"错误输出: {stderr.decode('utf-8', errors='ignore')}")
|
||
else:
|
||
logger.info("账号上传完成")
|
||
if stdout:
|
||
# 只记录最后几行输出
|
||
output_lines = stdout.decode('utf-8', errors='ignore').strip().split('\n')
|
||
for line in output_lines[-5:]:
|
||
logger.info(f"Upload: {line}")
|
||
except Exception as e:
|
||
logger.error(f"执行账号上传脚本时出错: {e}")
|
||
|
||
self.upload_process = None
|
||
|
||
def start_register(self):
|
||
"""启动注册进程"""
|
||
logger.info("启动注册进程")
|
||
try:
|
||
# 使用subprocess启动main.py
|
||
if sys.platform.startswith("win"):
|
||
register_process = subprocess.Popen(
|
||
["python", "main.py"],
|
||
creationflags=subprocess.CREATE_NEW_PROCESS_GROUP
|
||
)
|
||
else:
|
||
register_process = subprocess.Popen(
|
||
["python3", "main.py"]
|
||
)
|
||
|
||
logger.info(f"注册进程已启动,PID: {register_process.pid}")
|
||
return register_process
|
||
except Exception as e:
|
||
logger.error(f"启动注册进程时出错: {e}")
|
||
return None
|
||
|
||
async def run_service_check(self):
|
||
"""检查并启动/停止自动服务"""
|
||
enabled = await self.check_service_flag()
|
||
|
||
if enabled:
|
||
if not self.service_process or self.service_process.poll() is not None:
|
||
logger.info("自动服务标记已启用,但服务未运行,现在启动")
|
||
self.start_auto_service()
|
||
else:
|
||
if self.service_process and self.service_process.poll() is None:
|
||
logger.info("自动服务标记已禁用,但服务仍在运行,现在停止")
|
||
self.stop_auto_service()
|
||
|
||
return enabled
|
||
|
||
|
||
async def main():
|
||
"""主函数"""
|
||
parser = argparse.ArgumentParser(description="Cursor自动化服务管理工具")
|
||
group = parser.add_mutually_exclusive_group()
|
||
group.add_argument("--enable", action="store_true", help="启用自动服务")
|
||
group.add_argument("--disable", action="store_true", help="禁用自动服务")
|
||
group.add_argument("--status", action="store_true", help="查看自动服务状态")
|
||
group.add_argument("--upload", action="store_true", help="手动上传账号")
|
||
group.add_argument("--register", action="store_true", help="仅运行注册进程")
|
||
|
||
args = parser.parse_args()
|
||
|
||
manager = CursorServiceManager()
|
||
await manager.initialize()
|
||
|
||
try:
|
||
if args.enable:
|
||
await manager.set_service_flag(True)
|
||
manager.start_auto_service()
|
||
|
||
elif args.disable:
|
||
await manager.set_service_flag(False)
|
||
manager.stop_auto_service()
|
||
|
||
elif args.status:
|
||
enabled = await manager.check_service_flag()
|
||
print(f"自动服务状态: {'已启用' if enabled else '已禁用'}")
|
||
|
||
# 检查进程是否在运行
|
||
if manager.service_process and manager.service_process.poll() is None:
|
||
print(f"自动服务进程: 运行中 (PID: {manager.service_process.pid})")
|
||
else:
|
||
print("自动服务进程: 未运行")
|
||
|
||
elif args.upload:
|
||
manager.start_upload()
|
||
|
||
elif args.register:
|
||
register_process = manager.start_register()
|
||
if register_process:
|
||
print(f"注册进程已启动,PID: {register_process.pid}")
|
||
print("按Ctrl+C结束...")
|
||
try:
|
||
# 等待进程结束
|
||
register_process.wait()
|
||
except KeyboardInterrupt:
|
||
print("正在终止注册进程...")
|
||
if sys.platform.startswith("win"):
|
||
subprocess.run(["taskkill", "/F", "/T", "/PID", str(register_process.pid)])
|
||
else:
|
||
register_process.terminate()
|
||
|
||
else:
|
||
# 默认行为:检查并根据标记启动/停止服务
|
||
enabled = await manager.run_service_check()
|
||
print(f"自动服务状态: {'已启用' if enabled else '已禁用'}")
|
||
|
||
if enabled:
|
||
print("自动服务已启动,按Ctrl+C停止...")
|
||
try:
|
||
# 保持进程运行,等待用户中断
|
||
while True:
|
||
await asyncio.sleep(1)
|
||
except KeyboardInterrupt:
|
||
print("正在停止...")
|
||
|
||
finally:
|
||
await manager.cleanup()
|
||
|
||
|
||
if __name__ == "__main__":
|
||
asyncio.run(main()) |