Marco Nie https://blog.niekun.net/ zh-CN you are the company you keep... Thu, 14 Aug 2025 16:10:00 +0800 Thu, 14 Aug 2025 16:10:00 +0800 使用 Cython 对 python 代码加密打包 https://blog.niekun.net/archives/Cython-python.html https://blog.niekun.net/archives/Cython-python.html Thu, 14 Aug 2025 16:10:00 +0800 admin 目前我在使用 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 文件。

  1. Python 包管理约定:

    • 普通 .py 文件:可以放在任何 Python 路径中
    • 扩展模块 (.pyd/.so):通常放在 site-packages 中
  2. cx_Freeze 的处理逻辑:

    • 检测到 .py 文件 → 按源码文件处理 → 保持原目录结构
    • 检测到 .pyd 文件 → 按扩展模块处理 → 放入 site-packages
  3. 模块导入机制:

    • import src.library.function
    • Python 会在 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 函数。

]]>
0 https://blog.niekun.net/archives/Cython-python.html#comments https://blog.niekun.net/feed/archives/Cython-python.html
DeepWiki-open 生成项目 wiki https://blog.niekun.net/archives/DeepWiki-open-wiki-1.html https://blog.niekun.net/archives/DeepWiki-open-wiki-1.html Thu, 17 Jul 2025 13:57:00 +0800 admin 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/apikey
openai api:https://platform.openai.com/api-keys

根目录新建 .env 文件,配置环境变量:

GOOGLE_API_KEY=XXXXXXXXXXXXXXXXXXX
OPENAI_API_KEY=XXXXXXXXXXXXXXXXXXX
OPENROUTER_API_KEY=XXXXXXXXXXXXXXX

OPENROUTER_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,即可按照提示操作。

]]>
2 https://blog.niekun.net/archives/DeepWiki-open-wiki-1.html#comments https://blog.niekun.net/feed/archives/DeepWiki-open-wiki-1.html
建立本地 Web 服务器 https://blog.niekun.net/archives/3024.html https://blog.niekun.net/archives/3024.html Thu, 24 Apr 2025 09:04:00 +0800 admin 建立一个本地 Web 服务器来快速查看本地网站(HTML, CSS, JavaScript 文件)有几种非常快速的方法,通常只需要一行命令。这里介绍几种最常用的:

1. 使用 Python 内置的 HTTP 服务器 (通常最快,无需额外安装)

如果你的电脑上安装了 Python 3 (现在大多数操作系统都自带或容易安装),这是最快的方法之一,因为它不需要安装任何额外的库。

  • 步骤:

    1. 打开你的终端或命令提示符 (Terminal / Command Prompt / PowerShell)。
    2. 使用 cd 命令导航到你的网站文件所在的根目录(也就是包含 index.html 文件的那个文件夹)。
    3. 运行以下命令:

      python -m http.server
      • 如果你使用的是较旧的 Python 2 版本 (尽量避免使用),命令是:

        python -m SimpleHTTPServer
    4. 终端会显示类似 Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ... 的信息。
    5. 打开你的网页浏览器,访问 http://localhost:8000 或者 http://127.0.0.1:8000
    6. 如果你的根目录下没有 index.html,它会列出目录中的文件。
    7. 要停止服务器,回到终端按 Ctrl + C
  • 优点: 极快启动,通常无需安装额外软件。
  • 指定端口: 如果 8000 端口被占用,你可以指定其他端口:

    python -m http.server 8080

2. 使用 Node.js 的 http-serverlive-server (功能更强,需要 Node.js)

如果你安装了 Node.js 和 npm (Node Package Manager),可以使用一些非常方便的包。

  • a) http-server (基础服务器)

    1. 首次安装 (全局安装,只需一次):

      npm install -g http-server
    2. 启动服务器:

      • 在终端中,cd 到你的网站根目录。
      • 运行:

        http-server
    3. 终端会显示可用的访问地址,通常是 http://127.0.0.1:8080
    4. 在浏览器中打开该地址。
    5. Ctrl + C 停止。
  • b) live-server (带自动刷新功能)
    live-server 会在你修改并保存文件后自动刷新浏览器,非常适合开发调试。

    1. 首次安装 (全局安装,只需一次):

      npm install -g live-server
    2. 启动服务器:

      • 在终端中,cd 到你的网站根目录。
      • 运行:

        live-server
    3. 它通常会自动在你的默认浏览器中打开网站 (http://127.0.0.1:8080 或类似地址)。当你修改并保存 HTML/CSS/JS 文件时,浏览器会自动刷新。
    4. Ctrl + C 停止。
  • 优点: 功能更强(特别是 live-server 的自动刷新),Node.js 在 Web 开发中很常用。
  • 缺点: 需要先安装 Node.js 和对应的 npm 包。

3. 使用 VS Code 扩展 "Live Server" (集成在编辑器中,非常方便)

如果你使用 Visual Studio Code 编辑器,这是最方便的方法之一。

  • 步骤:

    1. 打开 VS Code。
    2. 转到扩展视图 (Extensions view, 图标通常在左侧边栏)。
    3. 搜索 "Live Server" (作者通常是 Ritwick Dey)。
    4. 点击 "Install" 安装。
    5. 安装完成后,打开你的网站项目文件夹。
    6. 在你的 index.html 文件上右键单击,选择 "Open with Live Server"。
    7. 或者,点击 VS Code 底部状态栏右下角的 "Go Live" 按钮。
    8. 服务器会启动,并在浏览器中自动打开页面,同样支持自动刷新。
    9. 要停止,可以再次点击状态栏的端口号按钮 (显示为 "Port: 5500" 或类似)。
  • 优点: 无需命令行操作,与编辑器紧密集成,带自动刷新。
  • 缺点: 需要使用 VS Code 编辑器。

4. 使用 PHP 内置服务器 (如果已安装 PHP)

如果你的系统碰巧安装了 PHP (通常用于后端开发,但也可用于快速启动静态服务器)。

  • 步骤:

    1. 打开终端或命令提示符。
    2. cd 到你的网站根目录。
    3. 运行:

      php -S localhost:8000
      • 你可以将 8000 替换为其他端口号。
    4. 在浏览器中访问 http://localhost:8000
    5. Ctrl + C 停止。
  • 优点: 如果已安装 PHP,则命令简单。
  • 缺点: 不如 Python 那么普遍预装,也不如 Node.js 工具或 VS Code 扩展功能丰富(如自动刷新)。

哪个最快?

  • 如果你有 Python: python -m http.server 通常是最快的,因为它很可能已经安装好了。
  • 如果你用 VS Code: 安装并使用 "Live Server" 扩展几乎是最方便、启动最快的方式(点击按钮即可)。
  • 如果你常用 Node.js: live-serverhttp-server 也非常快,并且 live-server 提供了非常有用的自动刷新功能。

选择哪种取决于你电脑上已有的环境和你个人的偏好。对于纯粹的“快速启动一个能看本地网页的服务器”,Python 的内置服务器通常拔得头筹。

]]>
0 https://blog.niekun.net/archives/3024.html#comments https://blog.niekun.net/feed/archives/3024.html
cloc 统计项目代码量 https://blog.niekun.net/archives/cloc.html https://blog.niekun.net/archives/cloc.html Wed, 26 Mar 2025 14:03:15 +0800 admin 最近需要对一个项目中的代码量进行统计,发现 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 的简单用法。

]]>
0 https://blog.niekun.net/archives/cloc.html#comments https://blog.niekun.net/feed/archives/cloc.html
honkit 使用教程及部署github page https://blog.niekun.net/archives/3021.html https://blog.niekun.net/archives/3021.html Fri, 17 Jan 2025 17:14:00 +0800 admin 1. 什么是 Honkit?

Honkit 是一个现代化的静态书籍生成工具,它是基于旧版 GitBook 开发的,支持 Markdown 文件的编写和多种输出格式,如 HTML 和 PDF。

2. 初始化 Honkit 项目

2.1 创建 Honkit 项目

  1. 创建项目目录

    mkdir my-honkit-project
    cd my-honkit-project
  2. 初始化 Honkit 项目

    npx honkit init

    这会生成以下两个文件:

    • README.md:书籍的主页面。
    • SUMMARY.md:目录结构的定义。
  3. 安装 Honkit

    npm install honkit --save-dev

3. 本地构建书籍

3.1 运行开发服务器

在项目目录中运行以下命令启动本地预览:

npx honkit serve

默认情况下,书籍会在 http://localhost:4000 上运行。

3.2 生成静态文件

当书籍准备好后,运行以下命令生成静态 HTML 文件:

npx honkit build

生成的文件会存储在 _book 目录中。


4. 生成 PDF 文件

Honkit 支持将书籍生成 PDF 文件,但需要预先安装 Calibre 电子书管理软件。

4.1 安装 Calibre

  1. 下载 Calibre

  2. 确保 Calibre 路径正确

    • 检查环境变量

      • 通常,Calibre 安装会自动将路径添加到系统的环境变量 PATH 中。
      • 如果未自动添加,手动将 Calibre 的安装目录路径添加到 PATH 环境变量中。
    • 例如,Windows 系统下,路径可能为:

      C:\Program Files\Calibre2
    • Linux 和 macOS 用户可通过以下命令验证:

      which ebook-convert

      如果返回路径为空,说明需要手动添加。

  3. 重新打开终端
    添加路径后,确保关闭并重新打开终端。

4.2 生成 PDF

运行以下命令生成 PDF 文件:

npx honkit pdf . output.pdf
  • . 表示当前目录。
  • output.pdf 是生成的 PDF 文件名。

5. 部署到 GitHub Pages

5.1 创建 GitHub 仓库

  1. 前往 GitHub 创建一个新仓库(例如 my-honkit-book)。
  2. 将本地项目与远程仓库关联:

    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 main

5.2 配置 GitHub Actions 自动部署

  1. 创建 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
  2. 提交配置文件
    提交并推送配置文件到 GitHub:

    git add .github/workflows/deploy.yml
    git commit -m "Add GitHub Actions for deployment"
    git push origin main
  3. 启用 GitHub Pages

    • 进入仓库的 Settings > Pages
    • Source 下选择 gh-pages 分支(如果没有需要手动新建此分支),点击保存。

6. 绑定自定义域名

6.1 配置 GitHub Pages

  1. 进入仓库的 Settings > Pages
  2. Custom domain 中输入您的自定义域名(例如 www.example.com)。
  3. 点击 Save。GitHub 会自动生成一个 CNAME 文件。

6.2 配置 DNS 记录

登录您的域名注册商控制台,添加以下 DNS 记录:

  • 绑定子域名(例如 www.example.com):
    添加 CNAME 记录

    www  CNAME  <username>.github.io
注意:将 <username> 替换为您的 GitHub 用户名。

6.3 启用 HTTPS

  1. 返回 GitHub 仓库的 Settings > Pages
  2. 勾选 Enforce HTTPS,以启用 HTTPS 访问。

自定义域名每次推送后消失的解决方法

当每次推送代码后,自定义域名设置消失,通常是由于 CNAME 文件被覆盖或删除。GitHub Pages 需要根目录的 CNAME 文件来保存自定义域名信息。如果该文件丢失或被覆盖,GitHub 就无法识别您的自定义域名。


解决方法

手动将 CNAME 文件添加到源码目录

  1. 创建 CNAME 文件
    在项目根目录(如 main 分支)下创建一个 CNAME 文件,并在文件中输入您的自定义域名,例如:

    www.example.com
  2. 提交更改
    提交并推送 CNAME 文件到远程仓库:

    git add CNAME
    git commit -m "Add CNAME file"
    git push origin main
  3. 验证
    每次部署后,CNAME 文件会自动被包含在 gh-pages 分支中,不会被覆盖。

验证步骤

  1. 检查 CNAME 文件

    • 进入 GitHub 仓库的 gh-pages 分支,确认根目录下有 CNAME 文件。
    • 文件内容应为您的自定义域名,例如:

      www.example.com
  2. 检查 GitHub Pages 设置

    • 转到 Settings > Pages
    • 确认自定义域名已正确显示,并启用 HTTPS
  3. 测试访问
    使用您的自定义域名访问页面,确认是否能够正确加载。

7. 常见问题及解决方法

问题 1:npx honkit pdf 报错 Command failed: ebook-convert not found

原因
Calibre 未正确安装,或 ebook-convert 工具未添加到系统的 PATH 环境变量中。

解决方法

  1. 确保 Calibre 已安装,并重新确认安装路径:

    • Windows 默认路径:C:\Program Files\Calibre2
    • macOS/Linux 使用 which ebook-convert 检查路径。
  2. 手动将 Calibre 的安装路径添加到系统环境变量中:

    • Windows

      • 打开“环境变量”设置,找到 PATH
      • 添加 C:\Program Files\Calibre2
    • Linux/macOS

      • 编辑 ~/.bashrc~/.zshrc 文件,添加以下内容:

        export PATH="/path/to/calibre:$PATH"

        替换 /path/to/calibre 为 Calibre 的实际路径。

      • 保存后运行 source ~/.bashrcsource ~/.zshrc 使更改生效。
  3. 重新运行 npx honkit pdf

问题 2:GitHub Actions 部署失败,提示 Permission denied

原因
GitHub Actions 无法向 gh-pages 分支推送更改,通常是因为缺少权限。

解决方法

  1. 确保 GitHub 仓库的 Settings > Actions > General 中已启用 Read and write permissions

    • 打开 Workflow permissions,选择 Read and write permissions
    • 勾选 Allow GitHub Actions to create and approve pull requests
  2. 确认 GitHub Actions 配置文件中使用的是 github_token

    with:
      github_token: ${{ secrets.GITHUB_TOKEN }}

问题 3:GitHub Pages 部署成功,但自定义域名未生效

原因
DNS 记录配置错误或未生效。

解决方法

  1. 登录域名管理平台,检查 DNS 配置:

    • 确认 A 记录或 CNAME 记录配置正确。
    • 等待 DNS 记录生效(可能需要 5-48 小时)。
  2. 检查仓库根目录下是否有 CNAME 文件,内容是否正确(应与自定义域名一致)。
  3. 验证 DNS 配置是否正确:

  4. 启用 HTTPS:

    • 进入 Settings > Pages,勾选 Enforce HTTPS

问题 4:生成的书籍内容显示错乱或样式缺失

原因

  • Markdown 文件中格式不正确。
  • SUMMARY.md 的目录结构未正确链接。

解决方法

  1. 确认 Markdown 文件的格式是否符合规范。
  2. 检查 SUMMARY.md 中的链接是否与文件路径一致:

    * [章节标题](path/to/file.md)
  3. 清理并重新构建书籍:

    npx honkit build

问题 5:自定义 PDF 样式未生效

原因
未指定自定义样式文件或样式文件路径错误。

解决方法

  1. 创建一个 CSS 样式文件(如 custom.css),自定义 PDF 的排版样式。
  2. 使用以下命令生成 PDF 并指定样式文件:

    npx honkit pdf --css custom.css . output.pdf

    8. 支持与反馈

如果您遇到未列出的问题或有其他疑问,请参考以下支持途径:

完成这些步骤后,您可以成功使用 Honkit 创建、部署和管理文档,解决常见问题,并生成符合您需求的 HTML 和 PDF 文档!

]]>
0 https://blog.niekun.net/archives/3021.html#comments https://blog.niekun.net/feed/archives/3021.html
docker compose 配置自动更新 https://blog.niekun.net/archives/docker-compose.html https://blog.niekun.net/archives/docker-compose.html Sun, 18 Aug 2024 21:42:00 +0800 admin 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 秒(即每小时)检查一次更新。
  • --cleanupWATCHTOWER_CLEANUP=true 确保在更新后清理旧的镜像。
  • --remove-volumesWATCHTOWER_REMOVE_VOLUMES=true 确保删除与旧容器关联的匿名卷。

使用这个配置,Watchtower 将:

  • 每小时检查一次你的容器是否有更新
  • 如果发现更新,它会停止旧容器,启动新容器
  • 删除旧的容器和相关的匿名卷
  • 删除旧的镜像

这个配置应该能满足大多数用例的需求,既能保持你的容器相对最新,又不会过于频繁地进行检查和更新操作。

需要注意的是:

  • Watchtower 只会删除它更新的容器的旧版本。它不会删除系统中的其他未使用的容器或镜像。
  • 它只删除匿名卷,不会删除命名卷。
  • 如果你想删除所有未使用的镜像(不仅仅是 Watchtower 更新的),你可能需要定期运行 docker image prune 命令。
]]>
0 https://blog.niekun.net/archives/docker-compose.html#comments https://blog.niekun.net/feed/archives/docker-compose.html
通过浏览器访问服务器指定文件内容 https://blog.niekun.net/archives/3014.html https://blog.niekun.net/archives/3014.html Wed, 14 Aug 2024 15:58:01 +0800 admin 通过 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 设置文件实际路径。

]]>
0 https://blog.niekun.net/archives/3014.html#comments https://blog.niekun.net/feed/archives/3014.html
将路径加入系统 path https://blog.niekun.net/archives/path.html https://blog.niekun.net/archives/path.html Sat, 10 Aug 2024 11:06:00 +0800 admin 将路径加入系统 path 可以方便的在终端调用目录中的可执行文件或脚本。windows 和 macOS 设置方法不同,下面分别介绍。

windows

参考之前的文章:https://blog.niekun.net/archives/413.html

macos

确定您的 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)。
  • 如果脚本名称与系统命令冲突,考虑重命名脚本或使用唯一前缀
]]>
0 https://blog.niekun.net/archives/path.html#comments https://blog.niekun.net/feed/archives/path.html
macOS 下使用 automator 给视频文件添加快捷压缩动作 https://blog.niekun.net/archives/macOS-automator.html https://blog.niekun.net/archives/macOS-automator.html Thu, 01 Aug 2024 14:42:36 +0800 admin 最近学习到了一条可以大幅度压缩视频体积且观感上视频质量没有很大损失的 ffmpeg 命令:

ffmpeg -i input.mov -c:v libx264 -crf 30 -r 24 -movflags faststart -c:a aac -b:a 128k -preset superfast out.mp4

但是每次在命令行执行这么复杂的命令还是很不方便的,可以使用 macOS 自带的 automator 自动化工具制作一个简单的右键菜单动作,方便的对视频文件快速压缩。

打开 automator 新建一个 quick action,添加一个 run sheel script:
image.png

脚本内容如下:

for f in "$@"
do
    /opt/homebrew/bin/ffmpeg -i "$f" -c:v libx264 -crf 30 -r 24 -movflags faststart -c:a aac -b:a 128k -preset superfast "${f%.*}_compressed.mp4"
done

# 播放声音
afplay /System/Library/Sounds/Blow.aiff

# 显示对话框
osascript -e 'tell app "System Events" to display dialog "视频压缩已完成" with title "通知" buttons {"OK"} default button "OK"'

保存后,在视频文件右键菜单的 action 栏就可以看到我们添加的动作了:
image.png

点击执行动作,完成后会有提示信息。

]]>
0 https://blog.niekun.net/archives/macOS-automator.html#comments https://blog.niekun.net/feed/archives/macOS-automator.html
使用虚拟环境 env 开发 python https://blog.niekun.net/archives/env-python.html https://blog.niekun.net/archives/env-python.html Mon, 01 Jul 2024 10:17:13 +0800 admin 使用虚拟环境进行Python开发有助于隔离项目的依赖,避免不同项目之间的库版本冲突。以下是如何创建和使用虚拟环境的详细步骤。

Python 3.3 及以上版本自带 venv 模块,可以直接使用。

使用 venv 创建虚拟环境

创建虚拟环境

在你的项目目录下,运行以下命令来创建一个虚拟环境,这将在项目目录下创建一个名为 myenv 的文件夹,其中包含虚拟环境的所有文件:

python -m venv myenv

激活虚拟环境

Windows:

myenv\Scripts\activate

macOS 和 Linux:

source myenv/bin/activate

安装依赖

在虚拟环境中,你可以使用 pip 来安装项目所需的库:

pip install requests

安装的库将只会影响当前虚拟环境,而不会影响系统的 Python 环境或其他项目。

冻结依赖

为了确保你的项目依赖可以在其他环境中重现,你可以使用以下命令将当前环境的依赖写入 requirements.txt 文件:

pip freeze > requirements.txt

requirements.txt 文件将包含所有当前环境中的安装包及其版本信息。

使用 requirements.txt 安装依赖

在新的环境中,你可以使用 requirements.txt 文件来安装所需的所有依赖:

pip install -r requirements.txt

退出虚拟环境

当你完成工作时,可以通过以下命令退出虚拟环境:

deactivate

使用虚拟环境进行Python开发可以有效地隔离项目依赖,避免版本冲突。通过创建和激活虚拟环境、安装依赖、冻结依赖并在新环境中重新安装依赖,可以确保你的项目在不同环境中具有一致的运行表现。

]]>
0 https://blog.niekun.net/archives/env-python.html#comments https://blog.niekun.net/feed/archives/env-python.html