Files
BakNRet/docs/adr/0007-run-lock-via-file-handle.md
T
Shuery 3a3a57a6a1 docs: 决策记录 8 条、变更日志、README 的验收与口令两节
0007 与 0008 是本次改造新产生的决策(原计划 6 条)。它们同样满足「后人会问为什么」:把运行锁改成互斥体、或给库里 27 个函数补上 SupportsShouldProcess,都是看起来更规范的错法。

CHANGELOG.md:把 README 里那 33 行「相对旧版修了什么」整节搬过去,并补上本次改造的记录(11 条修复 + 6 条结构与规范,每条修复都写明现象与现状)。README 那一节换成指针。

README 新增两节:「验收与静态分析」(六个层次、Run-RealSmoke 为什么独立存在、以及那 6 条格式规则默认 Disabled 这个容易漏掉的事实);「口令放在哪里」(默认留空不是遗漏,附迁移与验证命令)。

.markdownlint.json 照 PowerShell 主仓库的实践(default true、行长 240),只把 MD024 从关闭改成「仅同级不重复」,因为变更日志需要重复标题。顺带按 .editorconfig 把 .md 的 BOM 去掉。
2026-09-27 10:01:54 +08:00

23 lines
1.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 运行锁用独占文件句柄,而不是命名互斥体
`Backup.ps1` 与 `Restore.ps1` 都会写 `manifest.json`,也都会在备份目录里用 `<归档>.tmp`
这个名字生成临时归档。计划任务与手动运行撞在一起时,两边会互相覆盖对方的账本、把彼此的
临时归档当成自己的。计划任务的 `-MultipleInstances IgnoreNew` 只挡住"计划任务之间",
挡不住手动运行,所以需要一把跨进程的锁。
用**独占文件句柄**(`FileShare.None` 打开 `Backups\.baknret.lock`)而不是命名互斥体:
- 句柄由内核持有,进程被杀 / 崩溃时自动关闭,锁自动释放 —— 不会留下需要人工清理的陈旧锁;
- 命名互斥体要跨会话(计划任务在另一个会话里跑,互斥体是会话局部的)就得用 `Global\` 前缀,
而那需要额外权限;
- 文件系统的锁不区分会话与终端,计划任务与手动运行天然互相看见。
拿不到锁就**直接失败**(退出码 1 + 明确消息),不等待:单个条目压缩可能十几分钟,"等它跑完"
对用户来说和挂住没区别。锁文件里写明持有进程(pid / 起始时间 / 主机 / 用户)——"到底是谁
占着"这个问题不该靠猜。
只读模式不取锁(`-DryRun` / `-WhatIf` / `-VerifyOnly`):它们一个字节都不写。
代价:锁文件是备份目录里的一个额外文件(以 `.` 开头,归档枚举与孤儿审计都只看 `*.7z`,
不受影响);`Backups/` 被手工删除时锁也随之消失(这没关系,它本来就是运行期的)。