diff --git a/.gitignore b/.gitignore index 73ea2d0..d658fd5 100644 --- a/.gitignore +++ b/.gitignore @@ -44,4 +44,5 @@ coverage/ Thumbs.db # ---- Note 目录 ---- -note/项目/ \ No newline at end of file +note/项目/ +docs/plans \ No newline at end of file diff --git a/go/basics/runtime/main.go b/go/basics/runtime/main.go new file mode 100644 index 0000000..1dc160c --- /dev/null +++ b/go/basics/runtime/main.go @@ -0,0 +1,34 @@ +package main + +import ( + "fmt" + "runtime" +) + +var retained [][]byte // 全局变量,用来保持对象可达 + +func printMemory(stage string) { + var m runtime.MemStats + runtime.ReadMemStats(&m) + + fmt.Printf("%s: HeapAlloc=%d MiB, TotalAlloc=%d MiB\n", + stage, + m.HeapAlloc/1024/1024, + m.TotalAlloc/1024/1024) +} + +func main() { + runtime.GC() + printMemory("开始") + + for i := 0; i < 20; i++ { + block := make([]byte, 1024*1024) // 每次创建约 1 MiB 的底层数组 + block[0] = byte(i) + retained = append(retained, block) + } + printMemory("分配后") + + retained = nil // 程序不再持有这些数组 + runtime.GC() + printMemory("GC 后") +} \ No newline at end of file diff --git a/note/资源/DevOps/Git/常用命令.md b/note/资源/DevOps/Git/常用命令.md index e21e706..e683955 100644 --- a/note/资源/DevOps/Git/常用命令.md +++ b/note/资源/DevOps/Git/常用命令.md @@ -24,14 +24,14 @@ #### 三、远程操作 -| 操作 | 命令 | 说明 | -| ---------------- | --------------------------------------------------------- | ------------------- | -| 克隆仓库 | `git clone ` | 拉取远程项目 | -| 拉取远程代码 | `git pull` | 获取并合并远程分支 | -| 推送代码 | `git push` | 推送当前分支到远程 | -| 推送并设置上游 | `git push -u origin ` | 建立跟踪关系 | -| 查看远程地址 | `git remote -v` | 显示远程仓库地址 | -| 远程查询所有标签 | git ls-remote --tags https://github.com/xxx.git \| grep X | 查看X相关的所有标签 | +| 操作 | 命令 | 说明 | +| ---------------- | ----------------------------------------------------------- | ------------------- | +| 克隆仓库 | `git clone ` | 拉取远程项目 | +| 拉取远程代码 | `git pull` | 获取并合并远程分支 | +| 推送代码 | `git push` | 推送当前分支到远程 | +| 推送并设置上游 | `git push -u origin ` | 建立跟踪关系 | +| 查看远程地址 | `git remote -v` | 显示远程仓库地址 | +| 远程查询所有标签 | `git ls-remote --tags https://github.com/xxx.git \| grep X` | 查看X相关的所有标签 | #### 四、合并与变基 diff --git a/note/资源/编程/Golang/常用第三方库.md b/note/资源/编程/Golang/常用第三方库.md deleted file mode 100644 index 654e8b0..0000000 --- a/note/资源/编程/Golang/常用第三方库.md +++ /dev/null @@ -1,200 +0,0 @@ - - -### validator - -[GitHub地址](github.com/go-playground/validator) - -包验证器,可以用于验证参数是否符合规则,比如下方的比较验证,还有其他可以查看网址的详细介绍 -go-zero自带的有校验器,可以使用 - -| Tag | Description | -| ---- | --------------------- | -| eq | Equals | -| gt | Greater than | -| gte | Greater than or equal | -| lt | Less Than | -| lte | Less Than or Equal | -| ne | Not Equal | - - - -### goverter - -[GitHub地址](https://github.com/jmattheis/goverter) - -类型转换器,可以用于类型的转换,比如下面的代码 - -```go -func (l *CreatePopupLogic) CreatePopup(in *backgroundrpcmodel.ResPopup) (*backgroundrpcmodel.ResResult, error) { - _, err := l.svcCtx.PopupModel.Insert(l.ctx, u.Convert.SysPopupR2S(in.Info)) - if err != nil { - return nil, rerr.NewFromSQL(err) - } - return &backgroundrpcmodel.ResResult{ - Result: true, - }, nil -} -``` - -使用 - -``` -goverter gen . -``` - - - -### asynq - -[GitHub网址](https://github.com/hibiken/asynq) - -- 入队流程 - - ```go - payload := &jobtype.xxxPayload{} - payloadByte, err := jsoniter.Marshal(payload) - if err != nil { - logt.Error("xxx jsoniter.Marshal err:", err) - return nil, zerr.New(rescode.DataFormatConversionError) - } - _, err = l.svcCtx.AsynqClient.Enqueue(asynq.NewTask(jobtype.xxx, payloadBytes, asynq.Queue(consts.QueueLow))) - if err != nil { - logt.Error("xxx enqueue err:", err) - return nil, zerr.New(rescode.EnqueueErr) - } - ``` - -- 自行定义了队列优先级,在入队的时候可以加参数进行选择 - - ``` - consts.QueueCritical: 6, - consts.QueueDefault: 3, - consts.QueueLow: 1, - ``` - -- 处理前流程(反序列化,获取数据) - - ```go - var payload jobtype.xxx - err := json.Unmarshal(task.Payload(), &payload) - if err != nil { - logt.Error("xxx unmarshal payload err:", err) - return zerr.New(rescode.DataFormatConversionError) - } - ``` - - - -### gorm - -[官网文档](https://gorm.io/zh_CN/docs/) - -**使用gorm + sqlx,但是复用sql连接** - -```go -func NewServiceContext(c config.Config) *ServiceContext { - logx.Infof("Cache config: %+v", c.CacheRedis) - - gormDB, err := gorm.Open(postgres.Open(c.Database.DataSource), &gorm.Config{}) - if err != nil { - msg := fmt.Sprintf("连接数据库失败 %s ", err.Error()) - logx.Error(msg) - panic(msg) - } - sqlDB, err := gormDB.DB() - if err != nil { - msg := fmt.Sprintf("获取底层连接失败: %s", err.Error()) - logx.Error(msg) - panic(msg) - } - sqlxConn := sqlx.NewSqlConnFromDB(sqlDB) - return &ServiceContext{ - Config: c, - UserAuthModel: models.NewUserAuthModel(sqlxConn, c.CacheRedis, gormDB), - } -} -``` - - - -### excelize - -读写Excel的Go库 - -[github](https://github.com/qax-os/excelize) - -#### 创建工作簿 - -```go - f := excelize.NewFile() - defer func() { - if err := f.Close(); err != nil { - fmt.Println(err) - } - }() - // 创建一个新的Sheet,返回的index为该工作簿的索引 - index, err := f.NewSheet("SheetName") - if err != nil { - return fmt.Errorf("创建Sheet失败: %w", err) - } -``` - -#### 打开文件 - -```go - f, err := excelize.OpenFile(filePath) - if err != nil { - return fmt.Errorf("打开 Excel失败: %w", err) - } - defer func() { - if err := f.Close(); err != nil { - fmt.Println(err) - } - }() -``` - -#### 写入cell值 - -```go - f.SetCellValue("SheetName", "B2", 100) -``` - -#### 设置工作簿默认活动工作表 - -```go -f.SetActiveSheet(index) -``` - -#### 创建或更新excel表 - -```go - if err := f.SaveAs("Book1.xlsx"); err != nil { - return fmt.Errorf("保存失败: %w", err) - } -``` - -#### 获取指定cell值 - -```go - cell, err := f.GetCellValue("Sheet1", "B2") - if err != nil { - return fmt.Errorf("读取cell失败: %w", err) - } - fmt.Println(cell) -``` - -#### 获取所有工作簿的cell值(二维数组) - -```go - rows, err := f.GetRows("Sheet1") - if err != nil { - return fmt.Errorf("读取失败: %w", err) - } - for _, row := range rows { - for _, colCell := range row { - fmt.Print(colCell, "\t") - } - fmt.Println() - } -``` - diff --git a/note/资源/编程/Golang/常用第三方库/README.md b/note/资源/编程/Golang/常用第三方库/README.md new file mode 100644 index 0000000..2828a8a --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/README.md @@ -0,0 +1,8 @@ +# Go 常用第三方库 + +- [validator](validator.md) —— 参数校验器,验证参数是否符合规则 +- [goverter](goverter.md) —— 类型转换器,用于类型转换代码生成 +- [asynq](asynq.md) —— 异步任务队列,任务的入队与处理流程 +- [gorm](gorm.md) —— ORM,gorm + sqlx 复用 sql 连接的用法 +- [excelize](excelize.md) —— 读写 Excel 的 Go 库 +- [bcrypt](bcrypt.md) —— 密码哈希;Go 团队维护的官方扩展库 `golang.org/x/crypto/bcrypt`,不属于标准库 diff --git a/note/资源/编程/Golang/常用第三方库/asynq.md b/note/资源/编程/Golang/常用第三方库/asynq.md new file mode 100644 index 0000000..582299d --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/asynq.md @@ -0,0 +1,38 @@ +# asynq + +[GitHub网址](https://github.com/hibiken/asynq) + +- 入队流程 + + ```go + payload := &jobtype.xxxPayload{} + payloadByte, err := jsoniter.Marshal(payload) + if err != nil { + logt.Error("xxx jsoniter.Marshal err:", err) + return nil, zerr.New(rescode.DataFormatConversionError) + } + _, err = l.svcCtx.AsynqClient.Enqueue(asynq.NewTask(jobtype.xxx, payloadBytes, asynq.Queue(consts.QueueLow))) + if err != nil { + logt.Error("xxx enqueue err:", err) + return nil, zerr.New(rescode.EnqueueErr) + } + ``` + +- 自行定义了队列优先级,在入队的时候可以加参数进行选择 + + ``` + consts.QueueCritical: 6, + consts.QueueDefault: 3, + consts.QueueLow: 1, + ``` + +- 处理前流程(反序列化,获取数据) + + ```go + var payload jobtype.xxx + err := json.Unmarshal(task.Payload(), &payload) + if err != nil { + logt.Error("xxx unmarshal payload err:", err) + return zerr.New(rescode.DataFormatConversionError) + } + ``` diff --git a/note/资源/编程/Golang/常用第三方库/bcrypt.md b/note/资源/编程/Golang/常用第三方库/bcrypt.md new file mode 100644 index 0000000..d9c2859 --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/bcrypt.md @@ -0,0 +1,193 @@ +# 官方扩展库 `bcrypt` + +## `bcrypt` 是什么 + +`bcrypt` 是专门用于**密码哈希**的算法,不是可逆加密。 + +```text +password +↓ +bcrypt +↓ +hash +``` + +### 核心原则 + +```text +数据库只存 hash +bcrypt 自动处理 salt +使用 CompareHashAndPassword 验证 +cost 根据服务器性能决定 +不要自己用 MD5 / SHA256 存密码 +``` + +------ + +### cost + +`cost` 是 bcrypt 的计算难度。 + +生产环境通常可以从 `10 ~ 12` 开始测试,具体值应根据服务器性能决定。单次 bcrypt 计算控制在大约 `100ms ~ 300ms` 是比较常见的工程范围。 + +`cost` 每增加 1,计算量大约接近翻倍。 + +cost 越高: + +- 计算越慢 +- 暴力破解成本越高 +- 服务器 CPU 消耗也越高 + +bcrypt 生成的 hash 本身会记录当时使用的 `cost`。 + +因此,即使生产环境将当前配置从: + +```text +cost = 10 +``` + +升级为: + +```text +cost = 12 +``` + +数据库中原本使用 `cost = 10` 生成的旧 hash,仍然可以通过: + +```go +bcrypt.CompareHashAndPassword(...) +``` + +正常验证。 + +`CompareHashAndPassword` 会根据已有 hash 中记录的信息进行密码验证,不依赖当前系统配置的 cost。 + +登录成功后,可以通过 `bcrypt.Cost()` 获取旧 hash 使用的 cost。如果低于当前配置,可以重新生成 hash 并更新数据库。 + +------ + +### 72-byte 限制 + +bcrypt 密码输入最多支持约 `72 bytes`。 + +如果只允许 ASCII: + +```text +72 bytes ≈ 72 个字符 +``` + +通常已经足够。 + +建议业务层主动限制: + +```go +if len([]byte(password)) > 72 { + return errors.New("password too long") +} +``` + +------ + +## 基础使用 + +### 依赖导入 + +```go +import "golang.org/x/crypto/bcrypt" +``` + +`golang.org/x/crypto/bcrypt` 属于 Go 官方维护的扩展库,但不属于 Go 标准库。 + +------ + +### 生成 hash + +```go +hash, err := bcrypt.GenerateFromPassword( + []byte(password), + 12, +) +``` + +生成的 hash 类似: + +```text +$2a$12$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +``` + +其中大致包含: + +```text +$2a$ → bcrypt 版本 +12$ → cost +后续内容 → 编码后的 salt + hash +``` + +bcrypt 会自动生成随机 salt,因此不需要自己生成或额外保存 salt。 + +------ + +### 验证密码 + +```go +err := bcrypt.CompareHashAndPassword( + []byte(passwordHash), + []byte(password), +) + +if err == nil { + // 密码正确 +} +``` + +------ + +### 判断密码是否相同 + +不能直接比较两个 bcrypt hash,因为 bcrypt 每次都会生成新的随机 salt。 + +即使密码完全相同: + +```text +hash1 != hash2 +``` + +判断某个密码是否和旧密码相同时,应使用: + +```go +err := bcrypt.CompareHashAndPassword( + []byte(oldHash), + []byte(password), +) + +if err == nil { + // password 与 oldHash 对应的密码相同 +} +``` + +------ + +### 获取 hash 的 cost + +```go +cost, err := bcrypt.Cost( + []byte(user.PasswordHash), +) +``` + +通常用于**用户登录成功后**,判断当前密码 hash 是否使用了旧的 cost。 + +例如: + +```text +数据库 hash cost = 10 +当前系统 cost = 12 +↓ +登录成功 +↓ +重新生成 cost = 12 的 hash +↓ +更新数据库 +``` + +这样可以在用户正常登录过程中逐步升级旧密码 hash。 \ No newline at end of file diff --git a/note/随手记/casbin学习笔记.md b/note/资源/编程/Golang/常用第三方库/casbin.md similarity index 100% rename from note/随手记/casbin学习笔记.md rename to note/资源/编程/Golang/常用第三方库/casbin.md diff --git a/note/资源/编程/Golang/常用第三方库/excelize.md b/note/资源/编程/Golang/常用第三方库/excelize.md new file mode 100644 index 0000000..2c60f06 --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/excelize.md @@ -0,0 +1,80 @@ +# excelize + +读写Excel的Go库 + +[github](https://github.com/qax-os/excelize) + +## 创建工作簿 + +```go + f := excelize.NewFile() + defer func() { + if err := f.Close(); err != nil { + fmt.Println(err) + } + }() + // 创建一个新的Sheet,返回的index为该工作簿的索引 + index, err := f.NewSheet("SheetName") + if err != nil { + return fmt.Errorf("创建Sheet失败: %w", err) + } +``` + +## 打开文件 + +```go + f, err := excelize.OpenFile(filePath) + if err != nil { + return fmt.Errorf("打开 Excel失败: %w", err) + } + defer func() { + if err := f.Close(); err != nil { + fmt.Println(err) + } + }() +``` + +## 写入cell值 + +```go + f.SetCellValue("SheetName", "B2", 100) +``` + +## 设置工作簿默认活动工作表 + +```go +f.SetActiveSheet(index) +``` + +## 创建或更新excel表 + +```go + if err := f.SaveAs("Book1.xlsx"); err != nil { + return fmt.Errorf("保存失败: %w", err) + } +``` + +## 获取指定cell值 + +```go + cell, err := f.GetCellValue("Sheet1", "B2") + if err != nil { + return fmt.Errorf("读取cell失败: %w", err) + } + fmt.Println(cell) +``` + +## 获取所有工作簿的cell值(二维数组) + +```go + rows, err := f.GetRows("Sheet1") + if err != nil { + return fmt.Errorf("读取失败: %w", err) + } + for _, row := range rows { + for _, colCell := range row { + fmt.Print(colCell, "\t") + } + fmt.Println() + } +``` diff --git a/note/资源/编程/Golang/常用第三方库/gorm.md b/note/资源/编程/Golang/常用第三方库/gorm.md new file mode 100644 index 0000000..e546e3f --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/gorm.md @@ -0,0 +1,29 @@ +# gorm + +[官网文档](https://gorm.io/zh_CN/docs/) + +**使用gorm + sqlx,但是复用sql连接** + +```go +func NewServiceContext(c config.Config) *ServiceContext { + logx.Infof("Cache config: %+v", c.CacheRedis) + + gormDB, err := gorm.Open(postgres.Open(c.Database.DataSource), &gorm.Config{}) + if err != nil { + msg := fmt.Sprintf("连接数据库失败 %s ", err.Error()) + logx.Error(msg) + panic(msg) + } + sqlDB, err := gormDB.DB() + if err != nil { + msg := fmt.Sprintf("获取底层连接失败: %s", err.Error()) + logx.Error(msg) + panic(msg) + } + sqlxConn := sqlx.NewSqlConnFromDB(sqlDB) + return &ServiceContext{ + Config: c, + UserAuthModel: models.NewUserAuthModel(sqlxConn, c.CacheRedis, gormDB), + } +} +``` diff --git a/note/资源/编程/Golang/常用第三方库/goverter.md b/note/资源/编程/Golang/常用第三方库/goverter.md new file mode 100644 index 0000000..354f61b --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/goverter.md @@ -0,0 +1,23 @@ +# goverter + +[GitHub地址](https://github.com/jmattheis/goverter) + +类型转换器,可以用于类型的转换,比如下面的代码 + +```go +func (l *CreatePopupLogic) CreatePopup(in *backgroundrpcmodel.ResPopup) (*backgroundrpcmodel.ResResult, error) { + _, err := l.svcCtx.PopupModel.Insert(l.ctx, u.Convert.SysPopupR2S(in.Info)) + if err != nil { + return nil, rerr.NewFromSQL(err) + } + return &backgroundrpcmodel.ResResult{ + Result: true, + }, nil +} +``` + +使用 + +``` +goverter gen . +``` diff --git a/note/资源/编程/Golang/常用第三方库/validator.md b/note/资源/编程/Golang/常用第三方库/validator.md new file mode 100644 index 0000000..996ac0c --- /dev/null +++ b/note/资源/编程/Golang/常用第三方库/validator.md @@ -0,0 +1,15 @@ +# validator + +[GitHub地址](github.com/go-playground/validator) + +包验证器,可以用于验证参数是否符合规则,比如下方的比较验证,还有其他可以查看网址的详细介绍 +go-zero自带的有校验器,可以使用 + +| Tag | Description | +| ---- | --------------------- | +| eq | Equals | +| gt | Greater than | +| gte | Greater than or equal | +| lt | Less Than | +| lte | Less Than or Equal | +| ne | Not Equal | diff --git a/note/资源/编程/Golang/标准库.md b/note/资源/编程/Golang/标准库.md index 92bfd95..56bc280 100644 --- a/note/资源/编程/Golang/标准库.md +++ b/note/资源/编程/Golang/标准库.md @@ -22,6 +22,3 @@ if mysqlErr, ok := errors.AsType[*mysql.MySQLError](err); ok { } ``` - - -## `net/http/pprof` diff --git a/note/资源/编程/Golang/版本变化/1.27.md b/note/资源/编程/Golang/版本变化/1.27.md index d3bb54e..d55c4e9 100644 --- a/note/资源/编程/Golang/版本变化/1.27.md +++ b/note/资源/编程/Golang/版本变化/1.27.md @@ -96,199 +96,3 @@ Go 1.27 虽然开放了泛型方法,但有明确的限制: | **判断标准** | **是否为“空 (Empty)”** (如:空字符串 `""`、长度为 0 的切片/Map、`false`、`0`、指针 `nil`) | **是否为“ Go 类型的零值 (Zero Value)”** (满足 `reflect.Value.IsZero()` 或实现 `IsZero() bool` 接口) | | **结构体/时间类型处理** | **有重大缺陷**,对非指针的结构体(如 `time.Time`)无效!依然会被序列化。 | **完美支持** 未初始化的 `time.Time{}` 或任何嵌套结构体零值均会被正确跳过。 | | **自定义类型零值** | 不支持自定义零值判断逻辑。 | 支持只要实现 `IsZero() bool` 方法即可自定义是否跳过。 | - - - -## 官方扩展库 `bcrypt` - -### `bcrypt` 是什么 - -`bcrypt` 是专门用于**密码哈希**的算法,不是可逆加密。 - -```text -password -↓ -bcrypt -↓ -hash -``` - -#### 核心原则 - -```text -数据库只存 hash -bcrypt 自动处理 salt -使用 CompareHashAndPassword 验证 -cost 根据服务器性能决定 -不要自己用 MD5 / SHA256 存密码 -``` - ------- - -#### cost - -`cost` 是 bcrypt 的计算难度。 - -生产环境通常可以从 `10 ~ 12` 开始测试,具体值应根据服务器性能决定。单次 bcrypt 计算控制在大约 `100ms ~ 300ms` 是比较常见的工程范围。 - -`cost` 每增加 1,计算量大约接近翻倍。 - -cost 越高: - -- 计算越慢 -- 暴力破解成本越高 -- 服务器 CPU 消耗也越高 - -bcrypt 生成的 hash 本身会记录当时使用的 `cost`。 - -因此,即使生产环境将当前配置从: - -```text -cost = 10 -``` - -升级为: - -```text -cost = 12 -``` - -数据库中原本使用 `cost = 10` 生成的旧 hash,仍然可以通过: - -```go -bcrypt.CompareHashAndPassword(...) -``` - -正常验证。 - -`CompareHashAndPassword` 会根据已有 hash 中记录的信息进行密码验证,不依赖当前系统配置的 cost。 - -登录成功后,可以通过 `bcrypt.Cost()` 获取旧 hash 使用的 cost。如果低于当前配置,可以重新生成 hash 并更新数据库。 - ------- - -#### 72-byte 限制 - -bcrypt 密码输入最多支持约 `72 bytes`。 - -如果只允许 ASCII: - -```text -72 bytes ≈ 72 个字符 -``` - -通常已经足够。 - -建议业务层主动限制: - -```go -if len([]byte(password)) > 72 { - return errors.New("password too long") -} -``` - ------- - -### 基础使用 - -#### 依赖导入 - -```go -import "golang.org/x/crypto/bcrypt" -``` - -`golang.org/x/crypto/bcrypt` 属于 Go 官方维护的扩展库,但不属于 Go 标准库。 - ------- - -#### 生成 hash - -```go -hash, err := bcrypt.GenerateFromPassword( - []byte(password), - 12, -) -``` - -生成的 hash 类似: - -```text -$2a$12$xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -``` - -其中大致包含: - -```text -$2a$ → bcrypt 版本 -12$ → cost -后续内容 → 编码后的 salt + hash -``` - -bcrypt 会自动生成随机 salt,因此不需要自己生成或额外保存 salt。 - ------- - -#### 验证密码 - -```go -err := bcrypt.CompareHashAndPassword( - []byte(passwordHash), - []byte(password), -) - -if err == nil { - // 密码正确 -} -``` - ------- - -#### 判断密码是否相同 - -不能直接比较两个 bcrypt hash,因为 bcrypt 每次都会生成新的随机 salt。 - -即使密码完全相同: - -```text -hash1 != hash2 -``` - -判断某个密码是否和旧密码相同时,应使用: - -```go -err := bcrypt.CompareHashAndPassword( - []byte(oldHash), - []byte(password), -) - -if err == nil { - // password 与 oldHash 对应的密码相同 -} -``` - ------- - -#### 获取 hash 的 cost - -```go -cost, err := bcrypt.Cost( - []byte(user.PasswordHash), -) -``` - -通常用于**用户登录成功后**,判断当前密码 hash 是否使用了旧的 cost。 - -例如: - -```text -数据库 hash cost = 10 -当前系统 cost = 12 -↓ -登录成功 -↓ -重新生成 cost = 12 的 hash -↓ -更新数据库 -``` - -这样可以在用户正常登录过程中逐步升级旧密码 hash。 \ No newline at end of file diff --git a/note/随手记/Gitleaks.md b/note/随手记/Gitleaks.md new file mode 100644 index 0000000..45b5dc0 --- /dev/null +++ b/note/随手记/Gitleaks.md @@ -0,0 +1,41 @@ +# Gitleaks 使用笔记 + +Gitleaks 是扫描疑似密钥的命令行工具,不需要部署 Docker。它通过规则匹配识别令牌、云平台凭据、私钥等;命中不代表凭据仍有效,未命中也不代表绝对安全。 + +## Linux 安装 + +从 [官方 Releases](https://github.com/gitleaks/gitleaks/releases/latest) 下载对应架构的 Linux 压缩包:`uname -m` 为 `x86_64` 时选 `linux_x64`,为 `aarch64` 时选 `linux_arm64`。核对下载页提供的校验和,解压后安装: + +```sh +sudo install -m 0755 gitleaks /usr/local/bin/gitleaks +gitleaks version +``` + +## 提交前自动检测 + +在目标 Git 仓库中检查 `.git/hooks/pre-commit` 是否已存在;若存在,将下面的检测命令并入现有脚本,**不要覆盖**。新建时内容为: + +```sh +#!/bin/sh +gitleaks git --staged --redact --verbose . +``` + +然后运行 `chmod +x .git/hooks/pre-commit`。正常流程是 `git add <文件>` → `git commit -m "提交说明"`:Git 自动执行 hook;发现疑似密钥时命令返回非零状态,提交被阻止。`--redact` 避免在终端输出完整密钥。若设置了 `core.hooksPath`,应在指定的 hook 目录配置,而非 `.git/hooks/`。 + +## 手动扫描与测试 + +在仓库目录下运行: + +| 命令 | 检查范围 | +| --- | --- | +| `gitleaks git --staged --redact --verbose .` | 本次暂存变更的新增内容,与上面的 hook 一致 | +| `gitleaks git --redact .` | Git 提交历史中的新增内容 | +| `gitleaks dir --redact .` | 当前目录中的文件,包括尚未暂存的文件 | + +手动运行第一条命令可以先确认工具正常工作;没有命中通常返回 `0`,发现疑似密钥或扫描出错返回 `1`。普通文件修改不会因为装了 Gitleaks 就被阻止。要验证**自动拦截**,只用无效的模拟令牌测试,并先确认手动扫描能命中;随后运行普通的 `git commit`,预期 hook 阻止提交。若扫描未命中,别贸然提交测试令牌;若意外提交成功,不要推送,先检查 hook 是否执行及暂存内容。 + +## 注意事项 + +- `--staged` 扫描的是暂存差异中的新增内容,不等于检查每个暂存文件的全部历史内容;未暂存的修改也不在其中。 +- 本地 hook 通常只对当前仓库有效,且可被 `git commit --no-verify` 绕过;重要项目还应在 CI 中扫描。 +- 发现真实凭据时,先从暂存内容中移除并修复;若已推送或暴露,应尽快轮换凭据。误报可审慎使用 allowlist 或 `.gitleaksignore`,不要直接忽略未知来源的命中。 diff --git a/note/随手记/mcp.md b/note/随手记/mcp.md deleted file mode 100644 index d22a7fc..0000000 --- a/note/随手记/mcp.md +++ /dev/null @@ -1,5 +0,0 @@ -opencode添加mcp - -```bash -opencode mcp add postgres -- npx -y @microsoft/postgres-mcp run -``` \ No newline at end of file