code sync

This commit is contained in:
leimingsheng 2025-09-01 09:38:03 +08:00
parent 250512527e
commit 58e568869d
13 changed files with 343 additions and 7 deletions

@ -1 +1,28 @@
# D01_环境部署
操作系统: Windows
Python版本3.11.13
推荐使用Anaconda yml配置文件一键导入虚拟python环境
[配置文件路径](./../misc/okd-env.yml)
## 使用配置文件构建虚拟环境
Anaconda版本 conda 25.5.1
```shell
# 1.需要自行安装Anaconda, 建议安装同版本Anaconda
# 2.将okd-env.yml文件复制到目标设备
# 3.打开 Anaconda Prompt / 终端,执行重建命令:
conda env create --file 路径/文件名.yml
# 例如conda env create --file C:/Users/xxx/Desktop/okd-env.yml
# 4.等待 conda 自动下载并安装所有依赖包,完成后激活环境验证
conda activate okd-env
python --version
```

56
misc/okd-env.yml Normal file

@ -0,0 +1,56 @@
name: okd-env
channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/conda-forge/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/msys2/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/pytorch/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud/numba/label/dev/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/pro/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/mro/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main/win-64/
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/free/win-64/
- default
- defaults
dependencies:
- bzip2=1.0.8=h2466b09_7
- ca-certificates=2025.8.3=h4c7d964_0
- libexpat=2.7.1=hac47afa_0
- libffi=3.4.6=h537db12_1
- liblzma=5.8.1=h2466b09_2
- libsqlite=3.50.4=hf5d6505_0
- libzlib=1.3.1=h2466b09_2
- openssl=3.5.2=h725018a_0
- pip=25.2=pyh8b19718_0
- python=3.11.13=h3f84c4b_0_cpython
- setuptools=80.9.0=pyhff2d567_0
- tk=8.6.13=h2c6b04d_2
- tzdata=2025b=h78e105d_0
- ucrt=10.0.22621.0=h57928b3_1
- vc=14.3=h41ae7f8_31
- vc14_runtime=14.44.35208=h818238b_31
- vcomp14=14.44.35208=h818238b_31
- wheel=0.45.1=pyhd8ed1ab_1
- pip:
- altgraph==0.17.4
- click==8.2.1
- colorama==0.4.6
- packaging==25.0
- pefile==2023.2.7
- pyinstaller==6.15.0
- pyinstaller-hooks-contrib==2025.8
- pyqt6==6.4.2
- pyqt6-plugins==6.4.2.2.3
- pyqt6-qt6==6.4.3
- pyqt6-sip==13.10.2
- pyqt6-tools==6.4.2.3.3
- python-dotenv==1.1.1
- pywin32-ctypes==0.2.3
- qt6-applications==6.4.3.2.3
- qt6-tools==6.4.3.1.3
prefix: D:\Environment\Anaconda\envs\okd-env

@ -0,0 +1,6 @@
from .back_service import (
get_all_proj_name,
do_proj_parse
)
__all__ = [ get_all_proj_name, do_proj_parse ]

Binary file not shown.

Binary file not shown.

@ -0,0 +1,80 @@
import os
import importlib
def get_all_proj_dir():
proj_dirs = []
# 1.Search proj from src
from common import source_dir
backend_dir = os.path.join(source_dir, "backend")
# 检查路径是否存在
if not os.path.exists(backend_dir):
raise FileNotFoundError(f"指定路径不存在: {backend_dir}")
# 检查路径是否有效
if not os.path.isdir(backend_dir):
raise NotADirectoryError(f"指定路径不是一个目录: {backend_dir}")
for entry in os.listdir(backend_dir):
if entry.startswith("proj_"):
proj_dirs.append(entry)
# 2.Search proj from appdata
from common import get_user_appdata_path
app_dir = get_user_appdata_path()
usr_app_dir = os.path.join(app_dir, "onekeylog_diag")
usr_plugin_dir = os.path.join(usr_app_dir, "plugin")
# 检查路径是否存在
if not os.path.exists(usr_plugin_dir):
raise FileNotFoundError(f"指定路径不存在: {usr_plugin_dir}")
# 检查路径是否有效
if not os.path.isdir(usr_plugin_dir):
raise NotADirectoryError(f"指定路径不是一个目录: {usr_plugin_dir}")
for entry in os.listdir(usr_plugin_dir):
if entry.startswith("proj_"):
proj_dirs.append(entry)
return proj_dirs
def get_all_proj_name():
prefix_len = len("proj_")
proj_dir = get_all_proj_dir()
proj_name = [item[prefix_len:] for item in proj_dir]
return proj_name
def dynamic_import_lib(pacakge_name):
"""
动态拼接包名并导入模块
参数:
package_name : 包名
返回:
导入的模块对象,如果导入失败则返回None
"""
package_path = "backend." + pacakge_name
try:
# 动态导入模块
module = importlib.import_module(package_path)
print(f"成功导入模块: {package_path}")
return module
except ImportError:
print(f"无法导入模块: {package_path}")
return None
except Exception as e:
print(f"导入模块时发生错误: {e}")
return None
def do_proj_parse(key="app"):
porj_package = "proj_" + key
pHandlers = dynamic_import_lib(porj_package)
if hasattr(pHandlers, "start_parse"):
pHandlers.start_parse()

@ -0,0 +1,5 @@
from .service_app import (
start_parse
)
__all__ = [ start_parse ]

@ -0,0 +1,7 @@
import os
from common import record_log
SERVICE_TYPE = "APP"
def start_parse():
record_log("INFO", f"[{SERVICE_TYPE}] : Start Parse ...")

@ -1,8 +1,23 @@
from ._globals import (
cache_dir
cache_dir,
source_dir
)
def init_package_coomon():
pass
from .app_logger import (
record_log
)
init_package_coomon()
from .file_tool import(
force_empty_folder,
add_to_json_array,
get_user_appdata_path
)
# From ._globals
__all__ = [ cache_dir, source_dir ]
# From .app_logger
__all__ += [ record_log ]
# From .file_tool
__all__ += [ force_empty_folder, add_to_json_array, get_user_appdata_path ]

@ -1,12 +1,54 @@
import os
import time
from . import cache_dir
from app_logger import LOG_FILE
from ._globals import cache_dir
from .file_tool import force_empty_folder, add_to_json_array, get_user_appdata_path
from .app_logger import record_log
def app_cache_create():
if not os.path.exists(cache_dir):
os.makedirs(cache_dir)
# 在用户目录创建APP目录及插件目录
usr_appdata_path = get_user_appdata_path()
app_data_okd_path = os.path.join(usr_appdata_path, "onekeylog_diag")
if not os.path.exists(app_data_okd_path):
os.makedirs(app_data_okd_path)
record_log("Info", f"Create Dir:{app_data_okd_path}")
app_plugin_path = os.path.join(app_data_okd_path, "plugin")
if not os.path.exists(app_plugin_path):
os.makedirs(app_plugin_path)
record_log("Info", f"Create Dir:{app_plugin_path}")
def add_onekeylog_info_cache(log_name):
"""
添加一份新日志时触发这个动作, 将日志名称以及解析日期全部记录到
parse_history.json
参数
log_name(str): 被解析的文件名
"""
parseJsonFile = os.path.join(cache_dir, "parse_history.json")
# 获取当前时间戳
current_time = time.strftime("%Y-%m-%d %H:%M:%S")
# 生成新的记录Dict
new_entry = {
"filename" : log_name,
"timestamp" : current_time
}
result_b = add_to_json_array(parseJsonFile, new_entry)
if not result_b:
record_log("ERROR", "Fail to add parse history cache")
def clean_app_cache():
force_empty_folder(cache_dir)
def clean_running_log():
LOG_FILE = os.path.join(cache_dir, "running.log")
if os.path.exists(LOG_FILE):
os.remove(LOG_FILE)

@ -0,0 +1,98 @@
import os
import json
import shutil
import pathlib
def force_empty_folder(folder_path):
"""
强制清空指定文件夹内的所有内容包括文件和子文件夹但保留文件夹本身
参数:
folder_path (str): 要清空的文件夹路径
异常:
FileNotFoundError: 如果指定的文件夹不存在
PermissionError: 如果没有足够的权限操作文件夹内容
Exception: 其他可能出现的错误
"""
# 检查文件夹是否存在
if not os.path.exists(folder_path):
raise FileNotFoundError(f"文件夹不存在: {folder_path}")
# 检查路径是否指向一个文件夹
if not os.path.isdir(folder_path):
raise NotADirectoryError(f"指定路径不是一个文件夹: {folder_path}")
# 遍历文件夹内的所有内容
for item in os.listdir(folder_path):
item_path = os.path.join(folder_path, item)
try:
# 如果是文件或符号链接,直接删除
if os.path.isfile(item_path) or os.path.islink(item_path):
os.unlink(item_path)
# 如果是文件夹,递归删除整个文件夹
elif os.path.isdir(item_path):
shutil.rmtree(item_path, ignore_errors=False, onerror=None)
except Exception as e:
raise Exception(f"删除 {item_path} 时出错: {str(e)}")
def add_to_json_array(json_file_path, new_data):
"""
向JSON文件中的数组添加一组新数据
参数:
json_file_path (str): JSON文件的路径
new_data: 要添加到数组中的新数据可以是任何可序列化的类型字典列表字符串等
返回:
bool: 操作是否成功
异常:
IOError: 文件操作相关错误
json.JSONDecodeError: JSON格式解析错误
Exception: 其他可能的错误
"""
# 检查文件是否存在,如果不存在则创建并初始化一个空数组
if not os.path.exists(json_file_path):
with open(json_file_path, 'w', encoding='utf-8') as f:
json.dump([], f, ensure_ascii=False, indent=2)
# 读取现有数据
try:
with open(json_file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# 确保数据是一个数组
if not isinstance(data, list):
raise ValueError("JSON文件内容不是一个数组")
# 添加新数据
data.append(new_data)
# 写回文件
with open(json_file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=2)
return True
except json.JSONDecodeError:
raise json.JSONDecodeError(f"文件 {json_file_path} 不是有效的JSON格式", json_file_path, 0)
except Exception as e:
raise Exception(f"添加数据时发生错误: {str(e)}")
def get_user_appdata_path():
"""获取用户AppData目录路径"""
# 获取用户主目录
user_home = pathlib.Path.home()
# 根据操作系统获取AppData目录
if os.name == 'nt': # Windows系统
# 在Windows上AppData通常通过环境变量获取
appdata = os.getenv('APPDATA')
if appdata:
return pathlib.Path(appdata)
# 如果环境变量获取失败,使用默认路径
return user_home / 'AppData' / 'Roaming'
else:
raise OSError(f"不支持的操作系统: {os.name}")