Marco Nie https://blog.niekun.net/ you are the company you keep... sentinel 加密锁应用 https://blog.niekun.net/archives/sentinel.html 2025-10-10T14:03:00+08:00 最近使用 sentinel 的加密狗对软件进行加密,整个操作流程还是有一定门槛的,下面对安装到配置进行简要介绍。下载及安装 sentinel LDK官网下载地址:Sentinel-LDK_SDK备用下载:Sentinel-LDK选择下载最新的 sdk 和升级包:runtime 包用于客户端安装:安装最新版 SDK 及升级包,安装过程中注意选择本地模式的 EMS:配置主锁和产品启动程序前,插入 master 主锁和一个测试用的子锁。安装完成后启动 LDK,点击进入 master 主锁向导:初始默认用户名和密码都是:admin,按照提示下载需要的各种 API 支撑库文件:注意此处的文件就是主锁的开发商代码文件:开发商代码文件存放在用户目录下:Documents\Thales\Sentinel LDK 10.0\VendorCodes。二次开发需要用的 API 库文件存放在用户目录下:Documents\Thales\Sentinel LDK 10.0\API\Licensing。主锁 API 相关文件下载完成后,点击 LDK-EMS 进入管理界面:初始默认用户名和密码都是:admin,登录后会提示你需要修改密码。目录栏中切换到上面主锁向导中定义的开发商代码文件名,默认的 demoma 文件是一个用于测试的虚拟主锁文件:sentinel 的授权逻辑是:定义产品,唯一的 ID 号每个产品都可以有多个功能,每个功能配置唯一的 ID 号sentinel 的加密锁最终是通过功能 ID 号来识别是否授权而不是产品号所以我们即使有多个软件产品,每个软件产品有多个不同的功能块要授权,不同产品之间的功能块ID也需要不同,这样就不会出错了。我们做一个示例来说明如何定义一个产品。假设我们的产品名称为 EnveloGrinding,我们定义一个 login 的功能,用于软件登录的验证。进入功能选项卡,注意切换开发号到当前主锁的开发商代码名称,点击新功能选项,设置功能名称,以及唯一的功能 ID 号:点击确认后,此功能就在功能列表中了。然后进入产品选项卡,同样切换开发号到当前主锁的开发商代码,点击新产品:设置唯一的产品名称和 ID 号,在页面下方点击添加功能按钮,选择刚才创建的 login 功能:因为登录功能授权属于最基本的软件授权,所以这里选择此产品总是包含,如果其他更多的功能需要选择性的添加到产品,可以选择可以排除选项,这样再授权的时候就可以灵活组合授权哪些功能。点击另存为完成后,这个产品就定义成功了。此时我们给加密锁进行授权,将这个产品写入加密锁中。首选我们添加客户信息,也就是这个加密狗最终是交付给谁使用的,用于后期管理维护。客户选项卡点击新客户按钮:设置好所有信息后点击保存即可。点击授权选项卡,切换到正确的开发号后,点击新授权:首先在客户栏输入建立好的客户名称,这里不需要写全部字符,点击旁边的搜索图标,弹窗中点击搜索即可自动提取完整的客户信息。然后在下方点击添加产品,在弹窗中选择需要授权的产品即可:点击生成按钮进入最后的流程:如果已经插入了加密锁,此时会自动识别到下方的框里,选择一个加密锁,点击烧制即可将此产品授权写入加密锁中:以上就完成了基本的操作流程,此时加密锁已经授权了此产品中对应功能ID的授权。后续编程中需要对此功能 ID 进行检测,如果匹配即可验证成功。同时需要开发商代码 VendorCodes。加密锁授权更新如果需要对一个已经授权过的加密锁进行上面介绍的常规方式进行二次授权,会产生的现象是:以前老的授权功能 ID 依然可用,新的授权功能 ID 也可用。如果需要擦除老的授权,需要进行以下操作。点击新授权按钮后,选择保护锁更新,然后点击下方的查找按钮:点击锁ID,点击查找,在列表中选择需要更新的加密锁,然后点击添加到列表,然后点击确认即可:点击添加产品,选择当前需要更新的产品,然后点击生成:在弹窗中选择应用更新前清除锁,点击生成:此时会显示已生成 V2CP 文件,点击下载 V2CP 文件到本地:此时我们需要手动将此文件刷入加密锁中。点击进入控制管理中心:更新/依附栏选择下载的 V2CP 文件:点击应用文件可以将新授权刷入加密锁中。数据库备份与恢复EMS 数据库存放则产品/功能/授权/用户等重要信息,如果 ems 是本地模式则卸载软件或重装系统后数据就会丢失,所以定期备份数据很重要。官方教程:https://supportportal.thalesgroup.com/csm?sys_kb_id=52bcd4861b134850f12064606e4bcbca&id=kb_article_view&sysparm_rank=5&sysparm_tsqueryId=df79bdcd3be07614381ecfaf55e45aac&sysparm_article=KB0021094#2首先需要安装微软的 SQL Server Management Studio (ssms),官网地址:https://learn.microsoft.com/zh-cn/ssms/install/install,目前最新版为 ssms21。运行安装包后根据提示安装即可,如果安装失败,可能是系统缺少 Visual C++ runtime 库,需要自行手动安装以下。下载地址:https://learn.microsoft.com/en-us/cpp/windows/latest-supported-vc-redist安装 ssms 完成后即可启动 SQL Server Management Studio 应用程序,点击 connect object explorer:点击 browse 选择 emsdatabase:下方会自动填入相关信息,authentication 选择 sql server authentication,用户名为 sa,密码为 DBA!sa@EMSDB123,可选保存密码方便下次直接访问,encrypt 选择 optional,设置完成后点击 connect 连接:备份进入数据后,打开 databases,在 EMSDB 右键选择 task - backup:在 general 选项卡按照图片设置,然后点击 add 按钮添加备份文件地址:media option 中可以设置验证备份:设置完成后就可以直接按 ok 键备份了。恢复恢复方式也很简单,在 EMSDB 右键选择 task - restore - database:general 栏选择 device,然后点击按钮添加备份文件地址:在弹窗中点击 add 添加需要恢复的备份文件地址,完成后点击 ok 退出:此时就会显示从备份文件中读取到的数据库信息,在下方勾选需要恢复的数据库:这里需要注意的是,恢复 EMSDB 数据库需要先停止 EMS Service,否则会提示恢复失败。首先 win+R 弹出运行框,然后输入 Services.msc 并确认,打开服务窗口,在其中找到 Sentinel LDK-EMS Service 右键选择 stop 即可关闭此服务:关闭后回到 ssms,执行 ok 即可恢复此数据库:恢复完成后,需要重新启动 EMS Service 服务,同样的在 Sentinel LDK-EMS Service 服务右键选择 start 即可。以上就是 sentinel 加密锁的基本使用方法。 使用 dumpbin 检测 dll 文件中包含的函数 https://blog.niekun.net/archives/dumpbin-dll.html 2025-10-10T13:12:09+08:00 dumpbin 是微软 Visual Studio 工具集 自带的一个命令行工具,用于分析可执行文件(.exe、.dll、.obj、.lib)内部结构。dumpbin 位于 Visual Studio 工具链中,一般路径如下:C:\Program Files (x86)\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\<version>\bin\Hostx64\x64\dumpbin.exe 要使用它,可以通过以下方式:打开 “Developer Command Prompt for VS 2022”(开发者命令提示符),该环境自动配置好 PATH;然后在命令行中直接输入: dumpbin /?如果能看到帮助信息,说明环境已正确配置。查看 DLL 的导出函数dumpbin /exports your.dll 输出说明:Microsoft (R) COFF/PE Dumper Version 14.42.34433.0 Copyright (C) Microsoft Corporation. All rights reserved. Dump of file C:\Users\Marco Nie\TEST.dll File Type: DLL Section contains the following exports for hasp_windows_x64_107043.dll 00000000 characteristics 68DB892A time date stamp Tue Sep 30 15:39:22 2025 0.00 version 1 ordinal base 79 number of functions 79 number of names ordinal hint RVA name 1 0 00001000 MyFunctionA 2 1 00002000 MyFunctionB Summary A1000 .data D000 .pdata 133000 .rdata 6000 .reloc 1000 .rsrc 483000 .textordinal:函数序号name:导出函数名(重点)RVA:函数在文件中的相对虚拟地址用途:验证 DLL 是否正确导出了接口,比如你加密或封装的 DLL 是否暴露了预期的函数。如果想要检测是否包含特定名称的函数可以过滤结果:dumpbin /exports your.dll | findstr str111 以上指令会输出包含 str111 的行。查看 DLL 依赖的其他库dumpbin /imports your.dll 这会列出该 DLL 引用的其他 DLL(比如 KERNEL32.dll, USER32.dll 等)。查看 DLL 架构(32位 / 64位)dumpbin /headers your.dll | findstr machine 输出示例:14C machine (x86) 8664 machine (x64)查看完整头部信息(详细模式)dumpbin /all your.dll > result.txt 这样可以把所有信息输出到文件中慢慢查看,包括节区、符号、导入表、导出表、资源等。 使用 Cython 对 python 代码加密打包 https://blog.niekun.net/archives/Cython-python.html 2025-08-14T16:10:00+08:00 目前我在使用 cx_Freeze 对 python 程序打包成可执行文件,但是 cx_Freeze 的核心功能是将 Python 脚本、Python 解释器以及所有依赖的库文件打包到一个独立的可执行文件(如 Windows 下的 .exe 文件)或一个包含所有文件的目录中。打包后的文件中包含的是 Python 的字节码 .pyc 文件,这个文件是可以被反编译回近似的源代码的。通过使用 Cython 将 Python 源代码编译成 C 语言,然后再生成本地二进制文件(.pyd)。然后正常使用 cx_Freeze 打包,这样做可以极大地提高代码的保护级别,防止被轻易逆向。安装必要的 Python 包需要安装 Cython 和 Numpy,在终端或命令行中运行:pip install Cython numpy 安装 C/C++ 编译器Cython 将 Python 代码转换成 C 代码,但最终需要一个 C 编译器来将 C 代码编译成机器码。这是最关键的一步。对于 Windows 用户:访问 Visual Studio 下载页面:https://visualstudio.microsoft.com/zh-hans/downloads/。在 "Tools for Visual Studio" (所有下载 -> Visual Studio 工具) 中找到并下载 "Build Tools for Visual Studio"。运行安装程序,在 "工作负荷" 标签页中,勾选 "使用 C++ 的桌面开发"。点击安装。安装完成后,您可能需要重启电脑。对于 macOS 用户:打开终端并运行 xcode-select --install。这会安装苹果的命令行开发者工具,其中包含了 Clang 编译器。对于 Linux 用户 (例如 Ubuntu/Debian):打开终端并运行 sudo apt update && sudo apt install build-essential。修改 setup.py 文件如果项目目录结构如下:/my_project |-- main.py # 你的主程序文件 |-- /src # 你的其他模块目录 | |-- func1.py | |-- func2.py |-- setup.py # cx_Freeze 的配置文件根据以上目录结构,下面是一个配置文件示例:from cx_Freeze import setup, Executable import sys, os, io # ============================================================================= # Cython 自动化编译集成 # ============================================================================= try: from Cython.Build import cythonize from setuptools import Extension import numpy except ImportError: print("\n[错误] 缺少必要的库。请先安装 Cython 和 Numpy:") print("pip install Cython numpy") sys.exit(1) sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') # 修复非中文系统打包时报错 # 增加递归调用深度限制 sys.setrecursionlimit(1500) # 定义相关路径 ROOT_DIR = os.path.dirname(os.path.abspath(__file__)) ENTRY_POINT = "main.py" # 检查是否为打包命令 build_commands = {"build", "bdist_msi", "bdist_dmg", "bdist_mac"} is_building = any(cmd in sys.argv for cmd in build_commands) # --- Cython 编译配置 --- # 此函数会自动查找 src 目录下的所有 .py 文件并准备将它们编译 def find_extensions_to_compile(dir_path="src"): """Find all .py files to be compiled by Cython.""" extensions = [] # 添加 numpy 的头文件路径,这对于编译依赖 numpy/scipy 的代码至关重要 numpy_include = numpy.get_include() for root, dirs, files in os.walk(dir_path): for file in files: # 我们只编译 .py 文件,但跳过 __init__.py 文件 if file.endswith(".py") and file != "__init__.py": path = os.path.join(root, file) # 检查文件是否包含 numba 相关代码 try: with open(path, 'r', encoding='utf-8') as f: content = f.read() # 检查是否包含 numba 关键字 numba_keywords = ['from numba import', 'import numba', '@jit', '@njit', 'numba.jit', 'numba.njit'] has_numba = any(keyword in content for keyword in numba_keywords) if has_numba: print(f"--- 跳过包含 Numba 的文件: {path}") continue except Exception as e: print(f"--- 警告:无法读取文件 {path}: {e}") continue # 将文件路径转换为模块路径,例如 "src/library/function.py" -> "src.library.function" module_path = path.replace(os.sep, '.')[:-3] extensions.append( Extension( name=module_path, sources=[path], include_dirs=[numpy_include] # 包含 numpy 头文件 ) ) print(f"--- 找到 {len(extensions)} 个模块准备通过 Cython 编译...") return extensions # 仅在执行打包命令时才准备编译列表 extensions = [] if is_building: # 1. 编译 src 目录下的所有模块(自动排除包含 numba 的文件) extensions.extend(find_extensions_to_compile("src")) # ============================================================================= # cx_Freeze 配置 # ============================================================================= # 安装依赖 build_exe_options = { "packages": [ ], "excludes": ["email"] + [ext.name for ext in extensions], # 排除 Cython 编译的模块 "include_files": [ ], "includes": [], # 性能优化选项 "optimize": 2, # 使用Python优化 "include_msvcr": False, # 不包含MSVC运行库 } # 基础设置 base = "Win32GUI" if sys.platform == "win32" else None directory_table = [ # ... ] shortcut_table = [ ( # ... ), ( # ... ), ] msi_data = {"Directory": directory_table, "Shortcut": shortcut_table} bdist_msi_options = { # ... } executables = [ Executable( "main.py", # 入口文件 依然调用 py 程序,cx_Freeze 会自动识别并使用加密后的文件 # ... ) ] # ============================================================================= # 清理函数 # ============================================================================= def cleanup_generated_files(): """查找并删除由 Cython 生成的所有 .c 文件。""" print("\n--- 正在运行清理程序:删除生成的 C 文件... ---") for root, dirs, files in os.walk(ROOT_DIR): # 避免进入不相关的目录 if 'myenv' in root or '.git' in root or 'build' in root or 'dist' in root: continue for file in files: if file.endswith('.c'): file_path = os.path.join(root, file) try: os.remove(file_path) print(f"--- 已删除: {file_path}") except OSError as e: print(f"--- 删除失败 {file_path}: {e}") # ============================================================================= # 执行打包 # ============================================================================= try: setup( # ... # 关键步骤:将找到的 .py 文件交给 Cythonize 进行编译 ext_modules=cythonize( extensions, compiler_directives={'language_level': "3"}, # 使用 Python 3 语法 quiet=True # 减少不必要的编译输出 ) if is_building else [], # ... ) finally: # 只有在执行打包命令时才运行清理 if is_building: cleanup_generated_files()运行打包命令打包即可,如:python setup.py bdist_msi 检查加密情况安装完成后,进入安装路径的 Lib/site-packages 文件夹,会看到加密后的 .pyd 程序文件。.pyd 文件是 Windows 上的二进制动态链接库,本质上和 .dll 文件一样。如果加密失败:会在这里看到 .pyc 文件或者甚至原始的 .py 文件。Python 包管理约定:普通 .py 文件:可以放在任何 Python 路径中扩展模块 (.pyd/.so):通常放在 site-packages 中cx_Freeze 的处理逻辑:检测到 .py 文件 → 按源码文件处理 → 保持原目录结构检测到 .pyd 文件 → 按扩展模块处理 → 放入 site-packages模块导入机制:import src.library.functionPython 会在 sys.path 中搜索不加密:在 lib/ 中找到 src/library/function.pyc加密:需要在 lib/site-packages/ 中找到 src/library/function.pyd由于加密后的文件路径发生了变化,打包后访问加密后文件中的内容会报错,所以主程序在索引时需要特殊处理加密打包后的路径问题,主程序中使用下面函数可以自适应:# 路径修正代码 def fix_module_paths(): """修正打包后的模块搜索路径""" if getattr(sys, 'frozen', False): # 检查是否为打包后的可执行文件 # 获取可执行文件所在目录 base_dir = os.path.dirname(sys.executable) # 可能的src模块路径 possible_src_paths = [ os.path.join(base_dir, 'lib', 'site-packages'), # Cython编译后的位置 os.path.join(base_dir, 'lib'), # 标准位置 base_dir, # 根目录 ] # 将可能的路径添加到sys.path的开头 for path in possible_src_paths: if os.path.exists(path) and path not in sys.path: sys.path.insert(0, path) print(f"Added to Python path: {path}") # 特别检查src目录 src_path = os.path.join(base_dir, 'lib', 'site-packages', 'src') if os.path.exists(src_path): parent_dir = os.path.dirname(src_path) if parent_dir not in sys.path: sys.path.insert(0, parent_dir) print(f"Added src parent directory to Python path: {parent_dir}") # 执行路径修正 fix_module_paths()以上函数中,会将 src 文件夹下的函数库进行正确的索引。Numba 装饰器问题Numba 不兼容 Cython 编译后的函数。Numba 装饰器(如 @jit, @njit)期望装饰的是普通的 Python 函数,但 Cython 编译后生成的是 cython_function_or_method 类型,导致 Numba 无法识别。需要将包含 numba 的文件排除出编译列表。具体可见 setup.py 函数。 DeepWiki-open 生成项目 wiki https://blog.niekun.net/archives/DeepWiki-open-wiki-1.html 2025-07-17T13:57:00+08:00 DeepWiki-open可以为任何GitHub、GitLab或BitBucket代码仓库自动创建美观、交互式的Wiki,也可以提交本地仓库给它。试用了下发现效果还不错,可以作为项目开发指南。GitHub 主页:https://github.com/AsyncFuncAI/deepwiki-open使用方法很简单,clone 仓库代码,配置环境变量,启动前端和后端服务即可。下载git clone https://github.com/AsyncFuncAI/deepwiki-open.git cd deepwiki-open配置需要提前准备 openai 和 google ai 的 api key。Google AI api:https://makersuite.google.com/app/apikeyopenai api:https://platform.openai.com/api-keys根目录新建 .env 文件,配置环境变量:GOOGLE_API_KEY=XXXXXXXXXXXXXXXXXXX OPENAI_API_KEY=XXXXXXXXXXXXXXXXXXX OPENROUTER_API_KEY=XXXXXXXXXXXXXXXOPENROUTER_API_KEY 是可选项,其他两个是必须项。注意,我测试发现免费帐户的 openai api 在生成少数几个 wiki 后就会报错超出最大请求次数 error。而且项目必须使用 OpenAI-Compatible Embedding Models,解决方法是给 openai 充值或者使用 Alibaba Qwen 的 openai 兼容 api。alibaba qwen api:https://bailian.console.alibabacloud.com/?tab=app#/api-key如果使用其他 OpenAI-Compatible Embedding Models 需要将环境变量的 OPENAI_API_KEY 改为此第三方的 api key,然后在环境变量指定 OPENAI_BASE_URL:OPENAI_BASE_URL=https://dashscope-intl.aliyuncs.com/compatible-mode/v1 #示例中是 alibaba cloud 的 base url 地址然后修改 api/config/embedder.json 为:{ "embedder": { "client_class": "OpenAIClient", "initialize_kwargs": { "api_key": "${OPENAI_API_KEY}", "base_url": "${OPENAI_BASE_URL}" }, "batch_size": 10, "model_kwargs": { "model": "text-embedding-v3", "dimensions": 512, "encoding_format": "float" } }, "embedder_ollama": { "client_class": "OllamaClient", "model_kwargs": { "model": "nomic-embed-text" } }, "retriever": { "top_k": 20 }, "text_splitter": { "split_by": "word", "chunk_size": 350, "chunk_overlap": 100 } }使用安装环境并启动后端,提前建立一个虚拟环境:python -m venv .venv .venv\Scripts\activate pip install -r api/requirements.txt python -m api.main安装环境并启动前端:npm install npm run dev然后打开浏览器访问:http://localhost:3000,即可按照提示操作。 建立本地 Web 服务器 https://blog.niekun.net/archives/3024.html 2025-04-24T09:04:00+08:00 建立一个本地 Web 服务器来快速查看本地网站(HTML, CSS, JavaScript 文件)有几种非常快速的方法,通常只需要一行命令。这里介绍几种最常用的:1. 使用 Python 内置的 HTTP 服务器 (通常最快,无需额外安装)如果你的电脑上安装了 Python 3 (现在大多数操作系统都自带或容易安装),这是最快的方法之一,因为它不需要安装任何额外的库。步骤:打开你的终端或命令提示符 (Terminal / Command Prompt / PowerShell)。使用 cd 命令导航到你的网站文件所在的根目录(也就是包含 index.html 文件的那个文件夹)。运行以下命令:python -m http.server如果你使用的是较旧的 Python 2 版本 (尽量避免使用),命令是:python -m SimpleHTTPServer终端会显示类似 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 的信息。打开你的网页浏览器,访问 http://localhost:8000 或者 http://127.0.0.1:8000。如果你的根目录下没有 index.html,它会列出目录中的文件。要停止服务器,回到终端按 Ctrl + C。优点: 极快启动,通常无需安装额外软件。指定端口: 如果 8000 端口被占用,你可以指定其他端口:python -m http.server 80802. 使用 Node.js 的 http-server 或 live-server (功能更强,需要 Node.js)如果你安装了 Node.js 和 npm (Node Package Manager),可以使用一些非常方便的包。a) http-server (基础服务器)首次安装 (全局安装,只需一次):npm install -g http-server启动服务器:在终端中,cd 到你的网站根目录。运行:http-server终端会显示可用的访问地址,通常是 http://127.0.0.1:8080。在浏览器中打开该地址。按 Ctrl + C 停止。b) live-server (带自动刷新功能) live-server 会在你修改并保存文件后自动刷新浏览器,非常适合开发调试。首次安装 (全局安装,只需一次):npm install -g live-server启动服务器:在终端中,cd 到你的网站根目录。运行:live-server它通常会自动在你的默认浏览器中打开网站 (http://127.0.0.1:8080 或类似地址)。当你修改并保存 HTML/CSS/JS 文件时,浏览器会自动刷新。按 Ctrl + C 停止。优点: 功能更强(特别是 live-server 的自动刷新),Node.js 在 Web 开发中很常用。缺点: 需要先安装 Node.js 和对应的 npm 包。3. 使用 VS Code 扩展 "Live Server" (集成在编辑器中,非常方便)如果你使用 Visual Studio Code 编辑器,这是最方便的方法之一。步骤:打开 VS Code。转到扩展视图 (Extensions view, 图标通常在左侧边栏)。搜索 "Live Server" (作者通常是 Ritwick Dey)。点击 "Install" 安装。安装完成后,打开你的网站项目文件夹。在你的 index.html 文件上右键单击,选择 "Open with Live Server"。或者,点击 VS Code 底部状态栏右下角的 "Go Live" 按钮。服务器会启动,并在浏览器中自动打开页面,同样支持自动刷新。要停止,可以再次点击状态栏的端口号按钮 (显示为 "Port: 5500" 或类似)。优点: 无需命令行操作,与编辑器紧密集成,带自动刷新。缺点: 需要使用 VS Code 编辑器。4. 使用 PHP 内置服务器 (如果已安装 PHP)如果你的系统碰巧安装了 PHP (通常用于后端开发,但也可用于快速启动静态服务器)。步骤:打开终端或命令提示符。cd 到你的网站根目录。运行:php -S localhost:8000你可以将 8000 替换为其他端口号。在浏览器中访问 http://localhost:8000。按 Ctrl + C 停止。优点: 如果已安装 PHP,则命令简单。缺点: 不如 Python 那么普遍预装,也不如 Node.js 工具或 VS Code 扩展功能丰富(如自动刷新)。哪个最快?如果你有 Python: python -m http.server 通常是最快的,因为它很可能已经安装好了。如果你用 VS Code: 安装并使用 "Live Server" 扩展几乎是最方便、启动最快的方式(点击按钮即可)。如果你常用 Node.js: live-server 或 http-server 也非常快,并且 live-server 提供了非常有用的自动刷新功能。选择哪种取决于你电脑上已有的环境和你个人的偏好。对于纯粹的“快速启动一个能看本地网页的服务器”,Python 的内置服务器通常拔得头筹。 cloc 统计项目代码量 https://blog.niekun.net/archives/cloc.html 2025-03-26T14:03:15+08:00 最近需要对一个项目中的代码量进行统计,发现 cloc 可以完美的达到需求,简单命令行即可完成精确的统计。GitHub 主页:https://github.com/AlDanial/cloc常用语法统计文件夹中的代码构成:cloc /path/to/folder 统计当前文件夹:cloc . 排除文件夹中某些文件夹:cloc --exclude-dir=.github,myenv,build,dist . 效果如下:cloc --exclude-dir=.git,.idea,.vscode,.github,myenv,build,dist . 33 text files. 26 unique files. 23 files ignored. github.com/AlDanial/cloc v 2.04 T=0.16 s (162.0 files/s, 67602.7 lines/s) ------------------------------------------------------------------------------- Language files blank comment code ------------------------------------------------------------------------------- Python 22 1609 1947 6254 Markdown 2 114 0 484 JSON 1 0 0 403 Text 1 0 0 37 ------------------------------------------------------------------------------- SUM: 26 1723 1947 7178 -------------------------------------------------------------------------------以上就是 cloc 的简单用法。 honkit 使用教程及部署github page https://blog.niekun.net/archives/3021.html 2025-01-17T17:14:00+08:00 1. 什么是 Honkit?Honkit 是一个现代化的静态书籍生成工具,它是基于旧版 GitBook 开发的,支持 Markdown 文件的编写和多种输出格式,如 HTML 和 PDF。2. 初始化 Honkit 项目2.1 创建 Honkit 项目创建项目目录:mkdir my-honkit-project cd my-honkit-project初始化 Honkit 项目:npx honkit init这会生成以下两个文件:README.md:书籍的主页面。SUMMARY.md:目录结构的定义。安装 Honkit:npm install honkit --save-dev3. 本地构建书籍3.1 运行开发服务器在项目目录中运行以下命令启动本地预览:npx honkit serve默认情况下,书籍会在 http://localhost:4000 上运行。3.2 生成静态文件当书籍准备好后,运行以下命令生成静态 HTML 文件:npx honkit build生成的文件会存储在 _book 目录中。4. 生成 PDF 文件Honkit 支持将书籍生成 PDF 文件,但需要预先安装 Calibre 电子书管理软件。4.1 安装 Calibre下载 Calibre (与 honkit 兼容性最好的是 calibre 5.x 版本):访问 Calibre 官网:calibre release (5.44.0)。下载并安装适合您系统的版本。确保 Calibre 路径正确:检查环境变量:通常,Calibre 安装会自动将路径添加到系统的环境变量 PATH 中。如果未自动添加,手动将 Calibre 的安装目录路径添加到 PATH 环境变量中。例如,Windows 系统下,路径可能为:C:\Program Files\Calibre2Linux 和 macOS 用户可通过以下命令验证:which ebook-convert如果返回路径为空,说明需要手动添加。重新打开终端:添加路径后,确保关闭并重新打开终端。4.2 生成 PDF运行以下命令生成 PDF 文件:npx honkit pdf . output.pdf. 表示当前目录。output.pdf 是生成的 PDF 文件名。5. 部署到 GitHub Pages5.1 创建 GitHub 仓库前往 GitHub 创建一个新仓库(例如 my-honkit-book)。将本地项目与远程仓库关联:git init git remote add origin https://github.com/<username>/my-honkit-book.git git add . git commit -m "Initial commit" git branch -M main git push -u origin main5.2 配置 GitHub Actions 自动部署创建 GitHub Actions 配置文件:在项目的根目录下创建 .github/workflows/deploy.yml 文件,内容如下:name: Deploy Honkit to GitHub Pages on: push: branches: - main jobs: build: runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v3 - name: Setup Node.js uses: actions/setup-node@v3 with: node-version: '18' - name: Install Dependencies run: npm install - name: Build Honkit run: npx honkit build - name: Deploy to GitHub Pages uses: peaceiris/actions-gh-pages@v3 with: github_token: ${{ secrets.GITHUB_TOKEN }} publish_dir: ./_book提交配置文件:提交并推送配置文件到 GitHub:git add .github/workflows/deploy.yml git commit -m "Add GitHub Actions for deployment" git push origin main启用 GitHub Pages:进入仓库的 Settings > Pages。在 Source 下选择 gh-pages 分支(如果没有需要手动新建此分支),点击保存。6. 绑定自定义域名6.1 配置 GitHub Pages进入仓库的 Settings > Pages。在 Custom domain 中输入您的自定义域名(例如 www.example.com)。点击 Save。GitHub 会自动生成一个 CNAME 文件。6.2 配置 DNS 记录登录您的域名注册商控制台,添加以下 DNS 记录:绑定子域名(例如 www.example.com):添加 CNAME 记录:www CNAME <username>.github.io注意:将 <username> 替换为您的 GitHub 用户名。6.3 启用 HTTPS返回 GitHub 仓库的 Settings > Pages。勾选 Enforce HTTPS,以启用 HTTPS 访问。自定义域名每次推送后消失的解决方法当每次推送代码后,自定义域名设置消失,通常是由于 CNAME 文件被覆盖或删除。GitHub Pages 需要根目录的 CNAME 文件来保存自定义域名信息。如果该文件丢失或被覆盖,GitHub 就无法识别您的自定义域名。解决方法手动将 CNAME 文件添加到源码目录创建 CNAME 文件:在项目根目录(如 main 分支)下创建一个 CNAME 文件,并在文件中输入您的自定义域名,例如:www.example.com提交更改:提交并推送 CNAME 文件到远程仓库:git add CNAME git commit -m "Add CNAME file" git push origin main验证:每次部署后,CNAME 文件会自动被包含在 gh-pages 分支中,不会被覆盖。验证步骤检查 CNAME 文件:进入 GitHub 仓库的 gh-pages 分支,确认根目录下有 CNAME 文件。文件内容应为您的自定义域名,例如:www.example.com检查 GitHub Pages 设置:转到 Settings > Pages。确认自定义域名已正确显示,并启用 HTTPS。测试访问:使用您的自定义域名访问页面,确认是否能够正确加载。7. 常见问题及解决方法问题 1:npx honkit pdf 报错 Command failed: ebook-convert not found原因: Calibre 未正确安装,或 ebook-convert 工具未添加到系统的 PATH 环境变量中。解决方法:确保 Calibre 已安装,并重新确认安装路径:Windows 默认路径:C:\Program Files\Calibre2。macOS/Linux 使用 which ebook-convert 检查路径。手动将 Calibre 的安装路径添加到系统环境变量中:Windows:打开“环境变量”设置,找到 PATH。添加 C:\Program Files\Calibre2。Linux/macOS:编辑 ~/.bashrc 或 ~/.zshrc 文件,添加以下内容:export PATH="/path/to/calibre:$PATH"替换 /path/to/calibre 为 Calibre 的实际路径。保存后运行 source ~/.bashrc 或 source ~/.zshrc 使更改生效。重新运行 npx honkit pdf。问题 2:GitHub Actions 部署失败,提示 Permission denied原因: GitHub Actions 无法向 gh-pages 分支推送更改,通常是因为缺少权限。解决方法:确保 GitHub 仓库的 Settings > Actions > General 中已启用 Read and write permissions:打开 Workflow permissions,选择 Read and write permissions。勾选 Allow GitHub Actions to create and approve pull requests。确认 GitHub Actions 配置文件中使用的是 github_token:with: github_token: ${{ secrets.GITHUB_TOKEN }}问题 3:GitHub Pages 部署成功,但自定义域名未生效原因: DNS 记录配置错误或未生效。解决方法:登录域名管理平台,检查 DNS 配置:确认 A 记录或 CNAME 记录配置正确。等待 DNS 记录生效(可能需要 5-48 小时)。检查仓库根目录下是否有 CNAME 文件,内容是否正确(应与自定义域名一致)。验证 DNS 配置是否正确:使用 DNS Checker 验证域名解析。启用 HTTPS:进入 Settings > Pages,勾选 Enforce HTTPS。问题 4:生成的书籍内容显示错乱或样式缺失原因:Markdown 文件中格式不正确。SUMMARY.md 的目录结构未正确链接。解决方法:确认 Markdown 文件的格式是否符合规范。检查 SUMMARY.md 中的链接是否与文件路径一致:* [章节标题](path/to/file.md)清理并重新构建书籍:npx honkit build问题 5:自定义 PDF 样式未生效原因: 未指定自定义样式文件或样式文件路径错误。解决方法:创建一个 CSS 样式文件(如 custom.css),自定义 PDF 的排版样式。使用以下命令生成 PDF 并指定样式文件:npx honkit pdf --css custom.css . output.pdf8. 支持与反馈如果您遇到未列出的问题或有其他疑问,请参考以下支持途径:Honkit 官方文档:https://honkit.netlify.appGitHub 仓库:https://github.com/honkit/honkit社区支持:搜索相关问题或发帖提问。完成这些步骤后,您可以成功使用 Honkit 创建、部署和管理文档,解决常见问题,并生成符合您需求的 HTML 和 PDF 文档! docker compose 配置自动更新 https://blog.niekun.net/archives/docker-compose.html 2024-08-18T21:42:00+08:00 docker compose 配置文件可以很方便的配置和运行 docker 容器,手动更新容器的方法是在 yml 目录下运行以下命令:docker compose pull && docker compose up -d 可以通过在 compose 文件中设置 watchtower 来定期自动拉取最新镜像并启动容器,同时可以配置删除旧镜像和容器。在 docker-compose.yml 文件中增加以下内容:version: '3' services: ... watchtower: image: containrrr/watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock command: --interval 3600 --cleanup --remove-volumes environment: - WATCHTOWER_CLEANUP=true - WATCHTOWER_REMOVE_VOLUMES=true以下是主要的配置说明:将 --interval 参数设置为 3600。这意味着 Watchtower 将每 3600 秒(即每小时)检查一次更新。--cleanup 和 WATCHTOWER_CLEANUP=true 确保在更新后清理旧的镜像。--remove-volumes 和 WATCHTOWER_REMOVE_VOLUMES=true 确保删除与旧容器关联的匿名卷。使用这个配置,Watchtower 将:每小时检查一次你的容器是否有更新如果发现更新,它会停止旧容器,启动新容器删除旧的容器和相关的匿名卷删除旧的镜像这个配置应该能满足大多数用例的需求,既能保持你的容器相对最新,又不会过于频繁地进行检查和更新操作。需要注意的是:Watchtower 只会删除它更新的容器的旧版本。它不会删除系统中的其他未使用的容器或镜像。它只删除匿名卷,不会删除命名卷。如果你想删除所有未使用的镜像(不仅仅是 Watchtower 更新的),你可能需要定期运行 docker image prune 命令。 通过浏览器访问服务器指定文件内容 https://blog.niekun.net/archives/3014.html 2024-08-14T15:58:01+08:00 通过 nginx 可以反代服务器指定文件,然后就可以在网页中查看文件内容。核心就是通过 alias 关联文件路径。配置文件如下:location /test.log { alias /home/script/igd/app.log; default_type text/plain; add_header Content-Type "text/plain; charset=utf-8"; charset utf-8; # 确保不会缓存内容 add_header Cache-Control "no-cache, no-store, must-revalidate"; add_header Pragma "no-cache"; add_header Expires "0"; }location 路径替换为需要的路径。alias 设置文件实际路径。 将路径加入系统 path https://blog.niekun.net/archives/path.html 2024-08-10T11:06:00+08:00 将路径加入系统 path 可以方便的在终端调用目录中的可执行文件或脚本。windows 和 macOS 设置方法不同,下面分别介绍。windows参考之前的文章:https://blog.niekun.net/archives/413.htmlmacos确定您的 shell 类型。打开终端,运行以下命令:echo $SHELL 这通常会返回 /bin/zsh 或 /bin/bash。根据您的 shell 类型,编辑相应的配置文件:对于 Zsh(最新的 macOS 默认使用):编辑 ~/.zshrc对于 Bash:编辑 ~/.bash_profile 或 ~/.bashrc使用文本编辑器打开相应的文件。例如,对于 zsh:vim ~/.zshrc 在文件末尾添加以下行(替换为您的实际脚本目录路径):export PATH="/path/script:$PATH" 保存并关闭文件。使更改生效,可以重新加载配置文件或重启终端。要重新加载,运行:source ~/.zshrc # 如果使用 Zsh source ~/.bash_profile # 如果使用 Bash 验证 PATH 更新:echo $PATH 您应该能看到您的脚本目录已被添加。现在,您应该能够直接运行脚本,而不需要指定完整路径:test.sh 注意事项:确保您的脚本有正确的执行权限(chmod +x script_name.sh)。如果脚本名称与系统命令冲突,考虑重命名脚本或使用唯一前缀