Spaces:
Paused
Paused
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| """ | |
| 调试工具 - 用于分析 Clash Core 的运行环境 | |
| """ | |
| import os | |
| import sys | |
| import subprocess | |
| import logging | |
| import platform | |
| import json | |
| logger = logging.getLogger(__name__) | |
| def check_binary(binary_path): | |
| """检查二进制文件,并返回详细信息""" | |
| results = { | |
| "path": binary_path, | |
| "exists": os.path.exists(binary_path), | |
| "size": 0, | |
| "permissions": "", | |
| "file_type": "", | |
| "ldd_output": "", | |
| "system_info": get_system_info() | |
| } | |
| if results["exists"]: | |
| try: | |
| # 获取文件大小 | |
| results["size"] = os.path.getsize(binary_path) | |
| # 获取文件权限 | |
| results["permissions"] = oct(os.stat(binary_path).st_mode)[-3:] | |
| # 检查是否可执行 | |
| results["is_executable"] = os.access(binary_path, os.X_OK) | |
| # 获取文件类型 (file 命令) | |
| try: | |
| file_output = subprocess.check_output(["file", binary_path], universal_newlines=True) | |
| results["file_type"] = file_output.strip() | |
| except Exception as e: | |
| results["file_type_error"] = str(e) | |
| # 获取库依赖 (ldd 命令) | |
| try: | |
| ldd_output = subprocess.check_output(["ldd", binary_path], universal_newlines=True) | |
| results["ldd_output"] = ldd_output.strip() | |
| except Exception as e: | |
| results["ldd_error"] = str(e) | |
| # 尝试直接执行获取版本或帮助 | |
| try: | |
| version_output = subprocess.check_output([binary_path, "-v"], stderr=subprocess.STDOUT, universal_newlines=True, timeout=2) | |
| results["version_output"] = version_output.strip() | |
| except Exception as e: | |
| results["version_error"] = str(e) | |
| # 如果 -v 失败,尝试 --version | |
| try: | |
| version_output = subprocess.check_output([binary_path, "--version"], stderr=subprocess.STDOUT, universal_newlines=True, timeout=2) | |
| results["version_output"] = version_output.strip() | |
| except Exception as e2: | |
| results["version_error_alt"] = str(e2) | |
| except Exception as e: | |
| results["error"] = str(e) | |
| return results | |
| def get_system_info(): | |
| """获取系统信息""" | |
| info = { | |
| "platform": platform.platform(), | |
| "system": platform.system(), | |
| "release": platform.release(), | |
| "version": platform.version(), | |
| "architecture": platform.machine(), | |
| "python_version": sys.version, | |
| "cwd": os.getcwd(), | |
| "env": {key: value for key, value in os.environ.items()} | |
| } | |
| return info | |
| def check_clash_environment(clash_path, config_path): | |
| """检查 Clash 运行环境""" | |
| results = { | |
| "clash_binary": check_binary(clash_path), | |
| "config_file": { | |
| "path": config_path, | |
| "exists": os.path.exists(config_path), | |
| "size": 0, | |
| "content_preview": "" | |
| }, | |
| "directory_info": {} | |
| } | |
| # 检查配置文件 | |
| if results["config_file"]["exists"]: | |
| try: | |
| results["config_file"]["size"] = os.path.getsize(config_path) | |
| with open(config_path, 'r', encoding='utf-8') as f: | |
| content = f.read(1000) # 读取前1000个字符 | |
| results["config_file"]["content_preview"] = content | |
| except Exception as e: | |
| results["config_file"]["error"] = str(e) | |
| # 检查目录结构 | |
| dirs_to_check = [ | |
| os.path.dirname(clash_path), | |
| os.path.dirname(config_path), | |
| ".", | |
| "./data", | |
| "./clash_core", | |
| "./subconverter" | |
| ] | |
| for dir_path in dirs_to_check: | |
| try: | |
| if os.path.exists(dir_path): | |
| files = os.listdir(dir_path) | |
| results["directory_info"][dir_path] = { | |
| "exists": True, | |
| "files": files, | |
| "permissions": oct(os.stat(dir_path).st_mode)[-3:] | |
| } | |
| else: | |
| results["directory_info"][dir_path] = { | |
| "exists": False | |
| } | |
| except Exception as e: | |
| results["directory_info"][dir_path] = { | |
| "error": str(e) | |
| } | |
| return results | |
| def run_debug_diagnostics(clash_path, config_path): | |
| """运行调试诊断,并记录结果""" | |
| logger.info("运行调试诊断...") | |
| try: | |
| results = check_clash_environment(clash_path, config_path) | |
| logger.info("诊断完成") | |
| # 将结果保存到文件 | |
| diagnostics_file = "clash_diagnostics.json" | |
| with open(diagnostics_file, 'w', encoding='utf-8') as f: | |
| json.dump(results, f, indent=2, ensure_ascii=False) | |
| logger.info(f"诊断结果已保存到 {diagnostics_file}") | |
| # 打印关键信息 | |
| if results["clash_binary"]["exists"]: | |
| logger.info(f"Clash 二进制文件: {results['clash_binary']['path']}") | |
| logger.info(f" - 大小: {results['clash_binary']['size']} 字节") | |
| logger.info(f" - 权限: {results['clash_binary']['permissions']}") | |
| logger.info(f" - 文件类型: {results['clash_binary']['file_type']}") | |
| logger.info(f" - 可执行: {results['clash_binary'].get('is_executable', False)}") | |
| else: | |
| logger.error(f"Clash 二进制文件不存在: {results['clash_binary']['path']}") | |
| if results["config_file"]["exists"]: | |
| logger.info(f"配置文件: {results['config_file']['path']}") | |
| logger.info(f" - 大小: {results['config_file']['size']} 字节") | |
| preview = results["config_file"].get("content_preview", "") | |
| if preview: | |
| logger.info(f" - 内容预览: {preview[:100]}...") | |
| else: | |
| logger.error(f"配置文件不存在: {results['config_file']['path']}") | |
| return results | |
| except Exception as e: | |
| logger.error(f"诊断过程中出错: {str(e)}") | |
| return {"error": str(e)} |