clash / app /debug_tools.py
clash-linux's picture
Upload 17 files
03d4200 verified
#!/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)}