jameswintermute/hasher

GitHub: jameswintermute/hasher

一款纯 Shell 实现的 NAS 文件完整性监控与去重工具,通过 SHA-256 哈希快照检测静默损坏、追踪文件变更并安全清理重复文件。

Stars: 0 | Forks: 0

# Hasher — NAS 文件哈希工具、完整性监控与重复文件查找器 一个纯 shell 工具,通过 SHA-256 哈希为 NAS 上的每个文件建立目录。因此,你可以安全地查找重复文件、 reclaim space safely,并随着时间的推移,证明哪些文件发生了更改、消失或静默损坏。兼容 Synology DSM / BusyBox,除了标准的 Unix 工具外没有任何依赖。 ## Hasher 存在的意义 大型文件集合会悄无声息地衰退。几十年来积累的照片和文档在备份和导入过程中会产生重复文件;磁盘上的数据位会在毫无预兆的情况下发生腐化(bit-rot);文件可能会因为意外删除、磁盘故障、同步错误或恶意行为而消失,而且直到需要该文件时才发现它已经不见了。SHA-256 哈希是文件确切内容的指纹。如果你定期为每个文件生成指纹,你就掌握了一份精确的记录,记载了在每个时间点存在哪些文件以及每个文件的内容。这份记录是解答关乎长期数据完整性问题的关键基础: - **静默损坏** — 文件名和时间戳保持不变,但文件内容是否发生了变化?(这是 bit-rot 和篡改的典型特征。) - **静默或恶意删除** — 哪些文件上个月还在,现在却不见了,且没有任何故意的操作可以解释? - **变更追踪** — 自上次运行以来,添加、修改或移动了哪些内容? 去重是该工具立竿见影的一半功能:它查找相同的文件和完全相同的文件夹,帮助你安全地回收空间。完整性监控则是长期战略的另一半:相同且重复捕获的哈希值将成为审计追踪记录。 ## Hasher 是什么 Hasher 是一款**内容完整性工具**。它的唯一工作是可靠地计算文件哈希,并安全地根据这些哈希采取行动: - 通过 SHA-256 为每个文件建立目录(可选跨 CPU 核心并行执行) - 检测重复的**文件**(内容相同)和重复的**文件夹**(整个目录树完全相同——最高效的清理方式) - 安全移除重复文件:隔离优先,行动前规划,移动前重新验证 - 查找并移除零长度文件和 OS 垃圾残留物 - 每次运行都会输出带有时间戳的完整目录 CSV 文件 Hasher 刻意保持了功能的专一性。它计算哈希、查找重复项、安全移除并写入 CSV。它只专注做好一件事,从而保持足够小的体积以便于审计,并且足够稳定,值得信赖其在 NAS 上执行 root 级别的删除操作。 ## 完整性监控的工作原理 Hasher 本身不会将这次运行与上次运行进行对比(diff)——这超出了其范围,而正是这种克制使得核心程序保持了小巧。相反,**每次哈希运行都会将带有时间戳的 CSV 写入** `hashes/` 目录(`hasher-YYYY-MM-DD-HHMM.csv`):每个文件一行,记录其路径、大小、修改时间、算法和哈希值。 这些 CSV 是完整性监控的基础。由于每个 CSV 都是目录完整的、带有日期的快照,对比其中两个就能准确揭示发生了什么变化: - 存在于旧 CSV 但不存在于新 CSV 中的路径已被**删除**。 - 在两者中都存在,具有**相同的大小和 mtime 但哈希值不同**的路径,是**静默损坏或篡改**的指纹。 - 哈希值随 mtime 更新而改变的路径是正常的**编辑**。 - 仅存在于新 CSV 中的路径已被**添加**。 独立的、专门构建的工具会使用这些 CSV 并报告跨迭代的差异。将对比功能保留在独立的项目中,意味着系统中以 root 权限运行并移动文件的部分保持最小化且可审计,而只*读取* CSV 的分析功能可以独立演进。Hasher 的契约仅仅是生成诚实、完整、带时间戳的快照;你通过对比它们所获得的信息都是在此基础之上构建的。 ## 快速开始 ``` git clone https://github.com/jameswintermute/hasher.git cd hasher chmod +x launcher.sh bin/*.sh ./launcher.sh # first launch runs a short guided setup ``` 首次启动时,Hasher 会提供一个简短的、可跳过的引导设置:它会检查依赖项,帮助你为硬件选择合适的并行哈希级别,提示输入要扫描的目录,并向你展示隔离区的位置。它配置的所有内容之后也可以在菜单中访问。 ## 关于 项目作者:**James Wintermute** — jameswintermute@protonmail.ch 始于 2022 年 12 月。当前版本:**v1.3.2** 完整历史记录请参见:`version-history.md` ## 环境要求 - Synology DSM、macOS 或任何带有 bash 的 Linux 环境 - 标准工具:`bash`、`awk`、`sort`、`stat`、`find`、`mv`、`rm`、`xargs` - 推荐安装位置:你扫描的 volume 上的任何位置(例如 `/volume1/Tools/hasher`)。隔离区将在工具旁边创建。 跨平台支持已在 Synology DSM、Linux 和 macOS 上经过测试。感知宿主机环境的默认设置(排除项、隔离路径)通过 `lib/host-detect.sh` 自动应用。 ## 启动器菜单 ``` Stage 1 — Hash 1) Start hashing (NAS-safe defaults) a) Advanced / custom hashing s) Hashing status p) Performance settings (parallel hashing) Stage 2 — Identify 2) Find duplicate files 3) Find duplicate folders f) Find file by hash (lookup) Stage 3 — Review & clean 4) Review duplicate FILES (interactive) r) Review duplicate FOLDERS plan (interactive) 5) Auto-dedup (keep shortest path — no prompts) 6) Apply dedup plan (FILE or FOLDER) 7) Delete zero-length files 8) Delete junk (uses local/junk-extensions.txt) 9) Clean cache files & @eaDir (safe) Other d) System diagnostics (deps & readiness) l) Follow logs (tail -f background.log) t) Stats & scheduling hints v) Clean internal working files (var/) c) Clean logs (rotate & prune) q) Quit ``` 数字键 1–9 驱动主要工作流程。字母涵盖元数据和不常用的操作:`a`/`s`/`p` 用于哈希变体、状态和性能;`f` 用于哈希查找;`r` 用于文件夹计划审查;`d/l/t/v/c` 用于诊断和日常维护。 ## 性能 — 并行哈希 默认情况下,Hasher 串行(单线程)计算文件哈希,与其最初的行为保持一致。在具有 SSD 或 SHR 存储的多核系统上,并行哈希可以大幅减少大型任务的运行时间——因为在庞大的小文件语料库(如照片库)中,主导实际耗时的是单文件进程开销,而不是哈希运算。 通过 **`p` 菜单选项**(性能设置)设置线程数。它会检测你的 CPU 核心,推荐一个安全的值(`min(cores, 4)`),并将你的选择持久化到 `var/jobs.conf` 中。你也可以直接设置: ``` # 一次性: bin/hasher.sh --pathfile local/paths.txt --jobs 4 # 或者在 local/hasher.conf 中: [performance] jobs = 4 ``` 串行和并行运行产生相同的哈希输出;并行只是改变了行写入到 CSV 的顺序。 ## 推荐工作流程 ### 对于大型存储卷 — 使用自动去重(选项 5) 当你有成百上千个重复项组并且不需要逐组审查时,选项 5 一步即可处理整个过程: 1. 运行 **option 1** — 计算所有文件的哈希 2. 运行 **option 2** — 查找重复文件 3. 运行 **option 5** — 自动去重(生成计划并提供应用选项) 自动去重会保留每个重复项组中**文件路径最短**的副本,并将其他副本隔离。可配置为保留最长路径、最新或最旧的副本。 ### 谨慎审查 — 先处理文件夹,再处理文件 与逐个文件审查相比,文件夹去重每次决策能消除更多的冗余。请先运行它: 1. 运行 **option 1** — 计算所有文件的哈希 2. 运行 **option 3** — 查找重复文件夹 3. 运行 **option r** — 交互式审查文件夹计划;对每个组进行接受、跳过或交换保留项的操作;审查器会生成一份已审查的计划 4. 运行 **option 6** → `d` — 应用已审查的文件夹计划 5. 运行 **option 2** — 查找重复文件(现在数量会少得多) 6. 运行 **option 4** — 交互式审查文件组 7. 运行 **option 6** → `f` — 应用文件计划 当你运行选项 3 时,系统会立即为你提供审查器。如果你想先在另一个终端中检查计划,可以拒绝;随时可以通过选项 `r` 返回继续。 ## 计划文件 所有去重操作在移动任何文件之前,都会在 `logs/` 中生成一个纯文本计划文件。检查无误后再应用。 ``` # 查看将删除的内容(file dedup): cat logs/auto-dedup-plan-*.txt | grep '^DEL' | head -50 # 查看 folder dedup 计划: cat logs/duplicate-folders-plan-*.txt | head -20 # 在交互式审查文件夹之后: cat logs/duplicate-folders-plan-reviewed-*.txt ``` **文件计划格式**(每行一个决策,带有标记)。从 v1.2.0 开始,`DEL` 行带有预期内容哈希作为第三个字段,以便在隔离前对文件进行重新验证: ``` KEEP|/volume1/James/Photos/IMG_001.jpg DEL|/volume1/James/Backup/Photos/IMG_001.jpg|3a7bd3e2360a3d29eea436fcfb7e44c7... DEL|/volume1/James/Archive/Photos/IMG_001.jpg|3a7bd3e2360a3d29eea436fcfb7e44c7... ``` 旧版的双字段计划(`DEL|path`,无哈希)仍然被接受——只是会跳过重新验证,并发出警告,退回到存在性检查。 **文件夹计划格式**(每行一个路径;所有列出的路径都将被隔离;隐含的保留项是每个组中*未*列出的那个): ``` /volume1/James/Backup/Photos /volume1/James/Archive/Photos ``` 文件夹去重查找器还会写入一个 `duplicate-folders-groups-*.tsv` 辅助文件,其中包含完整的保留/删除结构以及可回收的空间大小,供审查器使用。所有标记为删除的文件都会被移至**隔离区**,而不是永久删除。 ## 配置 ``` default/hasher.conf — defaults (do not edit) local/hasher.conf — your overrides local/paths.txt — scan roots, one per line local/excludes.txt — find exclusion patterns local/exceptions-hashes.txt — hashes excluded from dedup local/excluded-from-dedup.txt — path prefixes excluded from dedup local/junk-extensions.txt — rules for junk file cleanup ``` 优先级:`CLI flags > local/hasher.conf > default/hasher.conf` 并行哈希优先级:`--jobs flag > hasher.conf [performance] jobs > var/jobs.conf(由 'p' 菜单设置)> HASH_JOBS env > default (1)`。 ## 目录结构 ``` hasher/ ├── bin/ │ ├── apply-folder-plan.sh │ ├── auto-dedup.sh │ ├── check-deps.sh │ ├── clean-logs.sh │ ├── csv-quick-stats.sh │ ├── delete-duplicates.sh │ ├── delete-junk.sh │ ├── delete-zero-length.sh │ ├── du-summary.sh │ ├── find-duplicate-folders.sh │ ├── find-duplicates.sh │ ├── hash-check.sh │ ├── hasher.sh │ ├── launch-review.sh │ ├── review-duplicates.sh │ ├── review-folder-plan.sh ← v1.1.13 │ ├── review-junk.sh │ └── run-find-duplicates.sh │ ├── lib/ │ └── host-detect.sh ← v1.1.9 │ ├── default/ │ └── hasher.conf │ ├── local/ — your config (gitignored) │ ├── exceptions-hashes.txt │ ├── excluded-from-dedup.txt │ ├── excludes.txt │ ├── hasher.conf │ ├── junk-extensions.txt │ └── paths.txt │ ├── logs/ — plan files and reports (gitignored) ├── hashes/ — hash CSVs (gitignored) ├── var/ — working files, jobs.conf (gitignored) ├── quarantine/ — files moved by delete-duplicates.sh │ ├── launcher.sh ├── LICENSE ├── readme.md └── version-history.md ``` ## 安全模型 **去重(核心工作流程)采用隔离优先原则,绝不执行永久删除:** - 在移动任何文件之前,都会生成计划并供审查 - **内容重新验证 (v1.2.0):**在隔离之前,`delete-duplicates.sh` 会重新计算每个候选项的哈希,如果内容不再与计划中的哈希匹配,则跳过该项——保护在规划和应用期间被修改的文件 - 文件夹去重审查器(选项 `r`)允许你在应用任何操作之前,对每个重复组进行接受、跳过或交换保留项的操作 - 应用原始(未经审查的)文件夹计划时会提示进行明确确认 - `delete-duplicates.sh` 和 `apply-folder-plan.sh` 将文件移至隔离区——而非永久删除;`apply-folder-plan.sh` 使用防冲突的隔离命名方式 (v1.1.6+) - 异常列表防止重新标记已知的重复项 **维护辅助脚本默认执行删除**——这些与去重是分开的,除非特别说明,否则将永久删除文件: - `delete-zero-length.sh` 删除空文件;传递 `--quarantine` 参数可改为移动它们 - `delete-junk.sh` 永久移除匹配 `local/junk-extensions.txt` 的文件 - cache/`@eaDir` 清理将永久移除这些缓存 - 所有脚本均支持 `--force`/dry-run 模式;请先审查计划或在未加 `--force` 的情况下试运行 **常规:** - 所有脚本在执行操作前都会立即重新验证路径 - 已审计 Bash 3.2 / BSD awk / macOS 用户空间兼容性 (v1.1.9–v1.1.12) ## 故障排除 **大小在重复审查中显示为 `??`** 通过 SSH 直接在 NAS 上运行 `review-duplicates.sh`——它无法 stat 远程路径。 **CSV 似乎已损坏** 修复换行符:`sed -i 's/\r$//' hashes/*.csv` **“All paths missing or unreadable” 错误** `local/paths.txt` 中的路径在当前主机上不存在。常见原因:外部驱动器未挂载、volume 名称拼写错误、NAS 共享脱机。使用 `ls /Volumes` (macOS)、`ls /mnt` 或 `ls /media` (Linux) 或 `ls /volume1` (Synology) 进行检查。 **文件夹审查提示 “no groups TSV found”** 请先运行选项 3(查找重复文件夹)。审查器会读取由查找器生成的 `logs/duplicate-folders-groups-*.tsv` 文件。 **“Content changed since plan was made — SKIPPING”** 预期且安全的行为:某个文件在计算哈希和应用期间发生了更改,因此它不再是经过验证的重复项。重新运行哈希和去重以重新评估它。 **并行哈希让我的 NAS 变慢了** 你可能在使用单个机械硬盘 (HDD)。通过 `p` 菜单将线程数设置回 1–2。并行有助于 SSD/SHR 阵列,对单盘无效。 ## 许可证 GNU GPLv3 — 详见 LICENSE。 ## 延伸阅读 - [Facebook — Silent Data Corruption](https://engineering.fb.com/2021/02/23/data-infrastructure/silent-data-corruption/) — 基于哈希的完整性监控的动机用例
标签:Cutter, NAS, SHA-256, Shell脚本, 去重, 完整性校验, 应用安全, 文件存储