跳转到主要内容

这是本节的多页打印视图。 .

返回本页常规视图.

其他

系统命令、云原生、开发工具等暂未单独分类的笔记

系统命令、云原生、开发工具这些暂时没单独分出去的笔记,都先放这里。

1 - Linux 常用命令速查

日常使用频率最高的 Linux 命令速查表,涵盖文件操作、进程管理、磁盘网络、权限系统等场景。

列出日常使用频率最高的命令。更多可参考 Linux 命令大全 | 菜鸟教程

系统信息

命令说明
uname -a显示操作系统名称、内核版本、主机名等详细信息
who -b显示系统上次启动时间
uptime显示系统运行时长和负载
hostnamectl查看或修改主机名
shutdown -h now立即关机
shutdown -h 1010 分钟后关机
reboot重启服务器

文件与目录

命令说明
pwd显示当前工作目录
cd <路径>切换目录
ls列出当前目录的文件和子目录
ls -la列出所有文件(含隐藏文件)及详细信息
mkdir <目录名>创建目录
rmdir <目录名>删除空目录
cp <源> <目标>复制文件或目录
mv <源> <目标>移动或重命名
rm <文件>删除文件
rm -rf <目录>强制递归删除目录(慎用)
touch <文件>创建空文件或更新文件时间戳
cat <文件>查看文件全部内容
less <文件>分页查看文件内容(按 q 退出)
head -n 20 <文件>查看文件前 20 行
tail -n 20 <文件>查看文件最后 20 行
tail -f <文件>实时追踪文件新增内容(如日志)

文件查找与内容搜索

命令说明
find <目录> -name "*.py"按文件名递归查找
grep "关键词" <文件>在文件中搜索文本
grep -r "关键词" <目录>递归搜索目录下所有文件
wc <文件>统计文件行数、单词数、字节数
wc -l <文件>仅统计文件行数
sort <文件>对文件内容排序

进程管理

命令说明
ps aux查看所有运行中的进程
ps -ef查看所有进程(另一格式)
top实时显示进程和系统资源占用
htoptop 的增强版(需安装)
kill <PID>终止指定进程
kill -9 <PID>强制终止进程
nohup <命令> &后台运行命令(退出终端后继续)

磁盘与内存

命令说明
df -h查看磁盘分区使用情况(人类可读)
du -sh <目录>查看目录总大小
free -h查看内存使用情况
free -m以 MB 为单位显示内存

网络

命令说明
ping <地址>测试网络连通性
curl <URL>发送 HTTP 请求
wget <URL>下载文件
ss -tlnp查看监听端口和对应进程
netstat -tlnp查看监听端口(ss 的替代)
ip addr查看网络接口和 IP 地址
ifconfig查看网络配置(需安装 net-tools)

文件权限

命令说明
chmod 755 <文件>设置文件权限
chmod +x <文件>给文件添加可执行权限
chown <用户>:<组> <文件>修改文件所属用户和组

压缩与归档

命令说明
tar -czf 包名.tar.gz <目录>打包并压缩为 tar.gz
tar -xzf 包名.tar.gz解压 tar.gz
unzip <文件>.zip解压 zip 文件
zip -r 包名.zip <目录>压缩为 zip

包管理(Debian/Ubuntu)

命令说明
apt update更新软件包索引
apt upgrade升级所有可升级的软件包
apt install <包名>安装软件包
apt remove <包名>卸载软件包
apt search <关键词>搜索软件包

2 - Markdown 语法速查

涵盖标题、文本、列表、链接、表格、代码等常用 Markdown 语法,一份速查表快速上手。

语法速查表

功能Markdown 语法效果预览
一级标题# 标题内容最大的标题
二级标题## 标题内容
三级标题### 标题内容(依此类推,可到六级)
加粗**需要加粗的文字**需要加粗的文字
斜体*需要倾斜的文字*需要倾斜的文字
加粗并斜体***又粗又斜的文字***又粗又斜的文字
删除线~~被删除的文字~~被删除的文字
无序列表- 列表项 或 * 列表项• 列表项
有序列表1. 列表项一
2. 列表项二
1. 列表项一
2. 列表项二
任务列表- [ ] 未完成
- [x] 已完成
☐ 未完成
☑ 已完成
引用> 这是一段引用的文字> 这是一段引用的文字
行内代码`code`用于突出显示变量或命令
代码块```python
print("Hello")
```
用于显示多行代码
链接[显示的文字](https://example.com)显示的文字
图片![替代文本](图片路径)直接显示图片
水平分割线--- 或 ***一条横跨页面的线

标题

注意:所有符号都是英文输入法下的符号。井号加空格,几个井号就是几级标题,一级标题字体最大。

# 一级标题
## 二级标题
### 三级标题
#### 四级标题
##### 五级标题
###### 六级标题

文本

**加粗**
*斜体*
***粗斜体***
~~删除线~~

列表

无序列表: 减号/加号/星号 + 空格,三个符号均可,建议用减号。

- 列表项 1
- 列表项 2
 - 嵌套列表项
- 列表项 3

有序列表: 数字 + 点 + 空格。

1. 列表项 a
2. 列表项 b
 1. 嵌套项 b1
3. 列表项 c

任务列表: 方括号内空格代表未完成,x 代表已完成。

- [ ] 未完成的任务
- [x] 已完成的任务

引用

> 这是一段引用
>> 嵌套引用

链接

[显示的文字](https://example.com)

直接链接:<https://github.com>

锚点链接:[链接文字][锚点名]
[锚点名]: https://example.com

图片

![替代文本](图片路径 "可选的标题")

带链接的图片:[![替代文本](图片路径)](https://example.com)

表格

竖线分隔单元格,分隔行至少三个减号,冒号控制对齐。

| 左对齐 | 居中对齐 | 右对齐 |
| :----- | :------: | -----: |
| AAA    |   BBB    |    CCC |

代码

行内代码:用反引号包裹,如 `code`。

代码块:用三个反引号包裹,可指定语言。

```python
import numpy as np
def calc(a):
    return np.sqrt(a) * 3
```

脚注

要添加脚注[^01]

[^01]: 脚注内容

分割线

三个或以上的减号、星号、下划线均可。

---
***
___

注意事项

  • 所有符号都是英文输入法下的符号
  • 井号 # 后要加空格才是标题

3 - MySQL 常用 SQL 语句速查

MySQL 常用 SQL 语句速查,涵盖数据库、数据表、数据行的增删改查及常用数据类型。

数据库操作

/* 创建数据库 */
CREATE DATABASE 数据库名称;

/* 删除数据库 */
DROP DATABASE 数据库名称;

/* 查看所有数据库 */
SHOW DATABASES;

/* 查看当前数据库的字符集等信息 */
SHOW CREATE DATABASE 数据库名称;

/* 修改数据库的字符集等属性 */
ALTER DATABASE 数据库名称 CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

数据表操作

/* 创建数据表 */
CREATE TABLE 数据表名称 (字段1 数据类型1, 字段2 数据类型2, ...);

/* 删除数据表 */
DROP TABLE 数据表名称;

/* 查看当前数据库中的所有数据表 */
SHOW TABLES;

/* 查看数据表的结构 */
DESCRIBE 数据表名称;

/* 查看数据表的创建语句 */
SHOW CREATE TABLE 数据表名称;

/* 添加新列 */
ALTER TABLE 数据表名称 ADD COLUMN 新字段 数据类型;

/* 修改列的数据类型 */
ALTER TABLE 数据表名称 MODIFY COLUMN 字段1 新数据类型;

/* 重命名列 */
ALTER TABLE 数据表名称 CHANGE COLUMN 字段1 新字段名 数据类型;

/* 删除列 */
ALTER TABLE 数据表名称 DROP COLUMN 字段1;

数据行操作

/* 插入数据行 */
INSERT INTO 数据表名称 (字段1, 字段2, ...) VALUES (值1, 值2, ...);

/* 查询数据行 */
SELECT 字段1, 字段2, ... FROM 数据表名称 WHERE 字段1 = '条件值1';

/* 更新数据行 */
UPDATE 数据表名称 SET 字段1 = '新值1', 字段2 = '新值2', ... WHERE 字段1 = '条件值1';

/* 删除数据行 */
DELETE FROM 数据表名称 WHERE 字段1 = '条件值1';

条件与排序

/* 条件查询 */
SELECT * FROM 数据表 WHERE 字段1 = '值';
SELECT * FROM 数据表 WHERE 字段1 LIKE '%关键词%';
SELECT * FROM 数据表 WHERE 字段1 > 100 AND 字段2 = '值';

/* 排序 */
SELECT * FROM 数据表 ORDER BY 字段1 DESC;        /* 降序 */
SELECT * FROM 数据表 ORDER BY 字段1 ASC;         /* 升序(默认) */

/* 分页 */
SELECT * FROM 数据表 LIMIT 10;                    /* 取前 10 条 */
SELECT * FROM 数据表 LIMIT 10 OFFSET 20;          /* 跳过 20 条,取 10 条 */
SELECT * FROM 数据表 LIMIT 20, 10;                /* 同上,简写形式 */

聚合与分组

/* 聚合函数 */
SELECT COUNT(*) FROM 数据表;                      /* 统计行数 */
SELECT SUM(金额字段) FROM 数据表;                  /* 求和 */
SELECT AVG(价格字段) FROM 数据表;                  /* 平均值 */
SELECT MAX(年龄字段) FROM 数据表;                  /* 最大值 */
SELECT MIN(年龄字段) FROM 数据表;                  /* 最小值 */

/* 分组统计 */
SELECT 分类字段, COUNT(*) FROM 数据表 GROUP BY 分类字段;
SELECT 分类字段, SUM(金额) FROM 数据表 GROUP BY 分类字段 HAVING SUM(金额) > 1000;

索引

/* 创建索引 */
CREATE INDEX 索引名称 ON 数据表 (字段1);
CREATE INDEX 索引名称 ON 数据表 (字段1, 字段2);   /* 联合索引 */

/* 删除索引 */
DROP INDEX 索引名称 ON 数据表;

/* 查看索引 */
SHOW INDEX FROM 数据表;

用户管理

/* 创建用户 */
CREATE USER '用户名'@'localhost' IDENTIFIED BY '密码';
CREATE USER '用户名'@'%' IDENTIFIED BY '密码';     /* 允许远程登录 */

/* 授权 */
GRANT ALL PRIVILEGES ON 数据库名.* TO '用户名'@'localhost';
GRANT SELECT, INSERT, UPDATE ON 数据库名.* TO '用户名'@'%';

/* 刷新权限 */
FLUSH PRIVILEGES;

/* 查看用户 */
SELECT User, Host FROM mysql.user;

/* 修改密码 */
ALTER USER '用户名'@'localhost' IDENTIFIED BY '新密码';

/* 删除用户 */
DROP USER '用户名'@'localhost';

常用数据类型

数值类型

数据类型说明取值范围适用场景
INT普通整数−21亿 ~ 21亿用户ID、文章数量、年份
BIGINT大整数−922亿亿 ~ 922亿亿订单号、日志ID、超大数据量
FLOAT单精度浮点数约 7 位有效数字科学计算、百分比
DOUBLE双精度浮点数约 15 位有效数字科学计算、高精度要求
DECIMAL定点数(精确)取决于定义金额、价格(必须用这个,避免精度丢失)

FLOAT(M,D) / DOUBLE(M,D) / DECIMAL(M,D) 中的 (M,D) 表示总长度 M 位,其中 D 位是小数。例如 DECIMAL(10,2) 总长 10 位,小数 2 位,整数 8 位。

字符串类型

数据类型说明最大长度适用场景
VARCHAR可变长度字符串65535 字符用户名、邮箱、标题(短文本首选)
TEXT长文本65535 字符文章正文、评论内容、日志详情

日期和时间类型

数据类型说明取值范围适用场景
DATETIME日期和时间1000 ~ 9999 年创建时间、更新时间(通用场景)
TIMESTAMP时间戳1970 年起记录日志时间,受时区影响(自动转换为当前时区)

DATETIME 和 TIMESTAMP 的区别:TIMESTAMP 会自动转换为当前时区;DATETIME 不受时区影响。日常场景首选 DATETIME。

JSON 类型

数据类型说明适用场景
JSON存储 JSON 格式数据配置信息、动态属性、非结构化数据存储

4 - SSH 密钥配置指南

SSH 密钥的生成、绑定、配置与常用操作,从入门到进阶。

简介

SSH 密钥(SSH Key)是一种用于安全登录远程服务器的"钥匙",它由一对公钥和私钥组成。与密码相比,SSH 密钥更安全,也更方便。

  • 公钥(Public Key):放在远程服务器上,可以公开。
  • 私钥(Private Key):保存在本地电脑,必须保密,不能泄露。

可以将其类比为钥匙(私钥)和锁芯(公钥),公钥放在远程服务器上,私钥保存在本地电脑里,相互配对才能正确打开。

生成密钥

在终端内执行:

  • 使用 ed25519 算法(推荐):ssh-keygen -t ed25519 -C "备注"
  • 使用 rsa 算法(兼容性好):ssh-keygen -t rsa -b 4096 -C "备注"

执行后,会让你确认密钥保存在哪里,是否需要再加一个密码。在一路回车的默认情况下,会在 ~/.ssh 目录下生成两个文件:

  • id_ed25519 或 id_rsa 即私钥
  • id_ed25519.pub 或 id_rsa.pub 即公钥

然后将公钥与远程服务器绑定即可。

绑定公钥

进阶:使用 ~/.ssh/config

服务器多起来后,每次 SSH 都要记 IP 和端口很麻烦。可以在 ~/.ssh/config 中为常用服务器设置别名:

# 个人服务器
Host my-server
    HostName 123.123.123.123
    User root

# Web 服务器
Host web-server
    HostName 456.456.456.456
    User admin
    Port 2222

配置后直接 ssh my-server 即可登录,不用再记 IP 和端口。

5 - VSCode 配置机制完整笔记

一、.vscode 目录概述

.vscode 是 VS Code 的项目级配置目录,定义"当 VS Code 打开这个项目时,该如何表现"。

常见文件结构

.vscode/
├── settings.json      # 工作区设置(覆盖用户全局设置)
├── extensions.json    # 推荐安装的扩展列表
├── launch.json        # 调试配置
├── tasks.json         # 自定义任务
└── snippets/          # 代码片段目录

二、配置层级与覆盖机制

三层架构(优先级由低到高)

VS Code 默认设置
    ↓
用户级设置(~/settings.json)
    ↓
工作区设置(.vscode/settings.json)← 项目级,优先级最高

关键区别

文件机制行为
settings.json增量覆盖只写3项 → 继承用户级其余7项
extensions.json全量清单只写a,b,c → 只推荐a,b,c,不继承其他
launch.json全量配置只显示配置的调试方案
tasks.json全量配置只显示定义的任务
snippets/*.json全量配置只提供定义的代码片段

示例对比

settings.json(增量)

// 用户级:a=1, b=2, c=3, d=4, e=5
// 项目级写:{"b": 20}
// 结果:a=1, b=20, c=3, d=4, e=5(继承+覆盖)

extensions.json(全量)

// 用户级:安装了 a,b,c,d
// 项目级写:{"recommendations": ["a","b"]}
// 结果:只推荐 a,b(不会推荐 c,d)

三、配置存储位置

用户级配置

类型路径(macOS/Linux)路径(Windows)
设置文件~/.config/Code/User/settings.json%APPDATA%\Code\User\settings.json
扩展目录~/.vscode/extensions/%USERPROFILE%\.vscode\extensions\
快捷键~/.config/Code/User/keybindings.json同左
代码片段~/.config/Code/User/snippets/同左

项目级配置

  • 位置:.vscode/ 目录下
  • 作用范围:仅当前项目
  • 版本控制:应提交到 Git,确保团队一致

四、扩展管理

用户级 vs 项目级

级别存储位置特点
用户级扩展~/.vscode/extensions/所有项目共享,物理安装在此
项目级推荐.vscode/extensions.json仅提示安装,不自动部署
真正隔离Dev Container容器内独立安装扩展

扩展推荐配置

{
  "recommendations": ["dbaeumer.vscode-eslint", "esbenp.prettier-vscode"],
  "unwantedRecommendations": ["some.extension.to.disable"]
}

多项目扩展隔离方案

场景:项目A用a,b,c,项目B用d,e,f,其他项目用a,b,c,d

方案实现方式适用场景
简单推荐extensions.json 分别配置只是提示,不强制
禁用配置settings.json 中禁用对方扩展扩展有冲突时
彻底隔离--user-data-dir 启动独立实例需要完全隔离

五、跨平台路径处理

核心原则

能用相对不用绝对,能用变量不用字符串

内置变量

变量含义跨平台效果
${workspaceFolder}项目根目录自动适配 Windows/macOS/Linux 路径格式
${userHome}用户主目录Windows: C:\Users\123, macOS: /Users/123
${workspaceFolderBasename}项目文件夹名如 project
${env:NAME}环境变量如 ${env:HOME}

正确 vs 错误示例

// ❌ 错误:硬编码绝对路径
"python.defaultInterpreterPath": "C:/Users/123/project/venv/bin/python"

// ✅ 正确:使用变量
"python.defaultInterpreterPath": "${workspaceFolder}/venv/bin/python"
"python.analysis.extraPaths": ["${userHome}/.local/lib/python"]

特殊情况处理

如果路径完全无关(如 Windows D:\project1\123 vs macOS Documents/project1/123):

方案做法
推荐把系统特定路径放用户级 settings.json,项目级保持通用
备选使用环境变量 ${env:PROJECT1_PATH}
避免硬编码不同系统的绝对路径到项目配置

六、VS Code 设置同步

同步内容

  • ✅ 用户级 settings.json
  • ✅ 扩展列表(自动重新安装)
  • ✅ 键盘快捷键
  • ✅ 用户级代码片段
  • ✅ UI 状态

不同步内容

  • ❌ 项目级 .vscode/ 目录(需 Git 管理)
  • ❌ 扩展的本地数据/缓存

分工明确

机制用途
设置同步个人习惯跟着账号走(跨设备)
.vscode + Git团队规范跟着代码走(跨成员)

七、最佳实践总结

1. 配置原则

  • 项目级(.vscode/):放团队共享、通用、跨平台的配置
  • 用户级(~/settings.json):放个人偏好、系统特定的配置

2. 路径原则

  • 优先使用 ${workspaceFolder}(项目内)
  • 其次使用 ${userHome}(用户目录)
  • 避免硬编码盘符(如 D:\、/Volumes/)

3. 扩展原则

  • 项目必需的扩展 → extensions.json 推荐
  • 个人辅助扩展 → 用户级安装,不同步到项目

4. 调试/任务原则

  • 通用任务 → .vscode/tasks.json(全量定义)
  • 个人调试习惯 → 用户级 launch.json

八、快速参考命令

操作命令面板(Ctrl+Shift+P)
打开用户级设置(UI)Preferences: Open User Settings
打开用户级设置(JSON)Preferences: Open User Settings (JSON)
打开工作区设置(JSON)Preferences: Open Workspace Settings (JSON)
打开扩展目录Extensions: Open Extensions Folder
打开键盘快捷键Preferences: Open Keyboard Shortcuts (JSON)

6 - MacOS 系统降级流程

本文介绍如何将 Intel 芯片的 MacOS 从 13.x 版本降级到 10.15 或 12.x 版本(已实测),其他版本仅供参考。

重要提示

降级过程会格式化全部磁盘内容,请务必提前备份所有重要数据,并在多处进行备份!

参考链接

MacOS 版本推荐

以下版本信息针对 2017 MacBook Pro 设备:

  • Ventura 13——最后一个支持的版本
  • Monterey 12——稳定性一般,兼容性较好
  • Catalina 10.15——稳定性最佳,兼容性一般

操作步骤

1. 准备工作

  1. 备份所有重要数据
  2. 退出系统的 Apple ID
  3. 准备一个 14GB 以上的 USB 闪存盘

2. 下载 MacOS

  1. 在 本页面 通过 App Store 下载所需的系统版本(如 Monterey 12)
  2. 下载完毕后,若自动打开安装程序,直接关闭退出
  3. 确保应用程序文件夹内有名为 安装macOS Monterey 的安装器

3. 创建 macOS 安装器

  1. 插入准备的 USB 闪存盘
  2. 使用系统自带的 磁盘工具 应用,将其全盘抹掉并格式化:
    • 名称:MyVolume(建议使用此名称,方便后续操作)
    • 格式:Mac OS拓展(日志式)(是否区分大小写不影响)
  3. 启动终端,根据所需的系统版本输入命令(命令来源):
    • Catalina:sudo /Applications/Install\ macOS\ Catalina.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
    • Monterey:sudo /Applications/Install\ macOS\ Monterey.app/Contents/Resources/createinstallmedia --volume /Volumes/MyVolume
  4. 根据终端提示完成安装:
    • 输入登录密码(输入时终端无字符提示)
    • 输入 Y 确认全部抹掉 USB 闪存盘(弹出允许终端访问可移动宗卷的提示时点击允许)
    • 耐心等待,过程较为漫长
  5. 安装完成后,USB 闪存盘名称将改为类似 Install macOS Monterey 的名称

4. 启动 MacOS 安装程序

  1. 重启设备后,立刻按住 Option 键,直到出现可引导安装器的宗卷(即 Install macOS Monterey)
  2. 通过方向键选择安装器(若无法启动,需确保“启动安全性实用工具”已设为允许从外部或可移动介质启动)

5. 安装 MacOS

  1. 进入安装器后,启动磁盘工具,抹掉内置的整个硬盘(通常被命名为 Macintosh HD):
    • 名称:Macintosh HD
    • 格式:APFS
  2. 关闭磁盘工具,返回选择 安装macOS Monterey
  3. 选择安装到 Macintosh HD
  4. 耐心等待,过程较为漫长

6. 完成安装

安装完成后,剩余步骤为初始化新的 MacOS 系统流程。

7 - Front Matter 规范

本站约定

  • title 是唯一必填字段,没有它 Hugo 无法渲染页面。
  • 日期使用本站自定义的 created / updated 字段,由 hugo.yml 的 frontmatter 映射到 Hugo 原生的 date / lastmod。
  • updated 一般不写——页面「最后修改」由 :git(最后一次 commit 时间)自动填充;手动写 updated 才会覆盖。
  • 编辑器可能对 created / updated 报 schema 错误,这是误报,勿改名(改名会破坏日期映射)。
  • 字段取值优先级:页面 front matter → 上级 cascade → hugo.yml 站点参数。

文章页字段

字段作用
title必需。页面标题,Hugo 没有它无法渲染页面
created创建日期,YYYY-MM-DD,页面显示为「创建于」
tags标签数组,如 [Docker, NAS],Hugo 自动生成标签页
description页面描述,用于搜索结果与社交分享;不写则自动截取正文前 70 字
updated手动指定更新日期;不写则由最后一次 commit 时间自动填充
weight列表内排序,数字越小越靠前
drafttrue 则页面不构建,hugo server --buildDrafts 下可见

OINK 主题常用字段

字段作用
linkTitle短标题,用于侧栏、面包屑与翻页器(正文大标题不变)
iconFont Awesome 图标类(如 fa-solid fa-rocket),用于侧栏与栏目卡片
categories分类,与 tags 同为 taxonomy,Hugo 自动生成分类页
series系列名;series_weight 决定在系列中的顺序
images封面图,第一项兼作社交分享卡片
sidebar_enabledfalse 隐藏左侧栏,独立页面常用
breadcrumbfalse 隐藏面包屑导航;博客分区默认关,其余默认开
notoctrue 则不显示右栏页面目录
pagerfalse 关闭本页底部上一页/下一页
backlinksfalse 隐藏右栏「反链」组(本站已在站点级开启)
comments评论开关:站点级已关闭
aliases旧路径重定向到本页,页面改名时用于保住旧评论串与外链

完整字段表见 OINK Front Matter 官方文档。

文章页模板

---
created: YYYY-MM-DD
title: 本文标题
tags: [标签1, 标签2]
---

索引页

各分区的 _index.md:

字段作用
title必需。分区名称
description分区描述,用于栏目卡片与 SEO
weight该分区在父级列表中的排序

日期机制

hugo.yml 中配置了 front matter 的取值优先级:

frontmatter:
  date:
    - created       # 第一优先级 → 页面创建日期
    - date
  lastmod:
    - updated       # 手动覆盖(可选)
    - :git          # 由 Git 提交记录自动填充
    - lastmod
  • 创建日期:Hugo 从 created 取值。
  • 更新日期:默认由 :git 自动填充(最后一次 commit 时间),如需手动指定,在 front matter 中写 updated 即可覆盖。

8 - 修复 Git 提交时间无法显示

问题现象

文章页面底部的"最后更新"时间始终不显示,检查 Hugo 模板发现 .GitInfo 和 .Lastmod 均为空值。

原因

当文件路径包含中文等非 ASCII 字符时(如 content/docs/实践笔记/Docker 重启策略详解.md),Git 默认会对路径做转义处理,导致 Hugo 的 Git 集成无法正确匹配文件路径,.GitInfo 返回 nil,.Lastmod 随之失效。

这是 Hugo 的已知问题,umlauts(ä、ö、ü)等路径也会触发。

解决方案

本地开发

在仓库根目录执行一次:

git config core.quotePath false

然后删除 .hugo_build.lock(缓存了旧状态),重新构建即可。

CI/CD 构建

.cnb.yml 中在 hugo 命令之前加上同一行:

- name: Hugo 构建
  script: |
    # 文件路径包含中文等字符时会导致 Hugo 拿不到 Git 提交时间,执行以下命令修复此问题
    git config core.quotePath false
    hugo --minify

验证

构建后检查页面 HTML,如果出现 hx:mt-12 而非 hx:mt-16,说明更新日期已正常显示。

参考