收起左侧

飞牛存储空间误删后的 Btrfs 只读恢复经历与开源工具 FNOS Rescue v0.1.1

0
回复
19
查看
[ 复制链接 ]

1

主题

0

回帖

0

牛值

江湖小虾

FNOS Rescue 数据恢复封面示意图> 封面图为 AI 生成示意图:源盘只读保护,恢复结果写入独立目标盘。## 写在最前面的安全警告如果你的飞牛存储空间被误删、磁盘无法挂载,第一件事不是“修复文件系统”,而是立刻停止向原盘写入。请不要在原盘上运行下面这些命令:- btrfs check --repair- btrfs rescue zero-log- btrfs rescue fix-device-size- mdadm --create- 任何格式化命令- 任何读写挂载操作我的处理原则只有三条:1. 源盘从物理设备、分区、md 设备到 loop 设备,全程只读;2. 必须测试历史元数据时,只写入以只读源盘为 backing file 的 QCOW2 覆盖层;3. 恢复出来的文件只写到另一块硬盘或网络共享,绝不写回源盘。数据重要或自己不能确认设备编号时,建议立即停手,先做完整镜像,或者交给专业数据恢复人员。下面分享的是技术路线,不是“复制一条命令就能无风险修好所有磁盘”的万能教程。## 事情是怎么发生的这次问题出现在飞牛 fnOS 的 Basic 单盘 Btrfs 存储空间上。存储空间删除或元数据损坏之后,系统还能识别到硬盘,但原来的 Btrfs 卷已经不能正常挂载。最让人困惑的是:- 硬盘能够被识别;- 部分 Btrfs 超级块或历史元数据仍然存在;- UFS Explorer 一类工具还能看到原来的目录、文件名和文件大小;- 但直接导出的文件可能打不开、内容不完整,甚至变成零字节;- 常规 btrfs restore 也可能因为 chunk tree、root tree、checksum tree 等元数据缺失而失败。这说明“目录名还看得见”不等于“文件数据已经正确恢复”。目录信息、inode、文件 extent 和物理 chunk 映射是不同层次的数据。只要其中一层被清空或指向错误位置,导出的文件就可能只有正确的名字和大小,实际内容却是坏的。## 最初容易走进的误区### 误区一:想办法把原盘重新挂载数据恢复的目标应该是把文件安全地复制出来,而不是强行让原文件系统恢复日常读写。强制修复和读写挂载可能覆盖仍可利用的历史树节点,让后续恢复更困难。### 误区二:UFS 能看到目录,导出的文件就一定有效UFS 提供的目录、文件名和推测大小非常有价值,但它更适合做“文件清单”和恢复优先级参考。文件是否真的恢复成功,还要检查文件头、内部结构、播放情况、压缩包完整性或哈希,不能只看文件名和大小。### 误区三:反复全盘扫描,却不保存扫描结果几 TB 的磁盘每扫一次都可能耗费很长时间。chunk 映射一旦扫出来就应该持久化缓存,后续更换历史 root 或重试单个 inode 时复用缓存,而不是从头再扫。## 最后采用的恢复思路只读恢复流程示意图*图 1(AI 生成示意图):只读源盘 → 可丢弃覆盖层/历史元数据 → 独立目标盘。*整个方案不是直接修改原盘,而是把 UFS 的目录信息与 Linux 下的只读 Btrfs 底层扫描组合起来。### 第一步:固定现场并记录磁盘身份先记录硬盘序列号、容量、分区、mdadm 数据偏移、Btrfs 起始偏移、FSID 和超级块 generation。所有后续命令都要核对序列号,避免选错盘。建议每块盘建立一个独立案例目录,至少保存:textdevice-facts.txtsuperblocks.txtroot-scan.logroot-candidates.tsvchunk-mappings.cachebtrfs-files.tsvufs-inventory.tsvufs-btrfs-match.tsvrestore.logfailed-files.tsvvalidated-samples.tsv### 第二步:检查全部 Btrfs 超级块镜像Btrfs 不只有一个超级块位置。主镜像损坏时,更后面的镜像可能还保留有效的 FSID、generation、root 地址和 system chunk array。这一步只读取和记录,不在原盘上改超级块。### 第三步:扫描历史 root磁盘上的当前 root tree 被破坏,不代表较早 generation 的树节点已经全部被覆盖。通过只读扫描物理 metadata block,可以找到历史 root tree、filesystem tree 和不同子卷的 root 候选。选择时不能只挑 generation 最大的一个,还要看:- root 与文件系统树是否属于同一个 FSID;- generation 是否连贯;- DUP metadata 的两份副本是否一致;- 对应 root 能否列出有效目录;- 是否能从代表性 inode 读出真实内容。### 第四步:建立 QCOW2 覆盖层如果需要让工具临时使用某个历史 root,只修改 QCOW2 overlay 中的超级块副本,并重新计算 checksum。原始磁盘保持只读不变。这样每次实验都可以丢弃覆盖层重新开始,不会把失败尝试写回源盘。### 第五步:恢复或重建 chunk 映射如果 chunk root 已经损坏,需要从磁盘上残存的 chunk item、device extent 和历史 device tree 中重建逻辑地址到物理 stripe 的映射。全量扫描结果保存为 chunk-mappings.cache。后面尝试不同历史 filesystem root、列目录或提取 inode 时,都复用这份缓存。### 第六步:把 UFS 清单与 Btrfs inode 对上从 UFS 导出完整路径、文件名、类型和大小,再与 Btrfs 列表进行匹配:1. 优先使用“完整路径 + 大小”精确匹配;2. 只有在结果唯一时,才使用“文件名 + 大小”匹配;3. 记录对应的 rootid、objectid/inode 和历史 root;4. 不把 UFS 显示的大小直接当成内容正确的证明。### 第七步:先恢复样本,再批量恢复先选择不同年代、不同目录、不同大小和不同格式的代表性文件,例如:- JPEG/PNG 图片:实际解码;- MP4/MOV 视频:用 ffprobe 检查并试播;- ZIP/Office 文件:运行 unzip -t7z t;- PDF:检查结构并实际打开;- 数据库或邮件文件:使用对应应用或结构检查工具验证。样本验证通过后,再批量恢复目录。恢复过程允许跳过坏文件,但必须生成失败清单,保留原始相对路径、预期大小、inode、失败原因和尝试过的历史 root。### 第八步:区分“真正的空文件”和“恢复失败的占位文件”零字节文件不一定原本就是空文件。只有结合 UFS 清单、Btrfs inode 大小和提取日志,才能区分:- 原本就是零字节的文件;- 因 extent 或 chunk 映射错误而提取失败的文件;- 工具为了保留目录结构生成的占位文件。在失败清单完成前,不要随意删除这些占位文件;后续找到更合适的历史 root 或物理 stripe 后,可以只重试失败 inode。## 我把流程做成了 FNOS RescueFNOS Rescue Web 界面*图 2:FNOS Rescue Web 开发界面截图,设备为演示数据。*为了让这套过程更安全、可重复,我把相关能力整理成了开源项目 FNOS Rescue。GitHub 仓库:https://github.com/superms-lab/fnos-rescue项目定位不是“自动修复原盘”,而是一个 只读优先、证据可追溯、恢复到其他介质 的工具箱。目前包括:- Linux/fnOS 下的磁盘与 Btrfs 只读诊断;- Btrfs 历史 root 扫描工具;- 带持久化 chunk cache 的高级 Btrfs 恢复工具;- 历史目录树浏览、inode 定向提取和批量恢复;- 失败清单、进度记录、断点续作与样本验证;- 本机 Web 恢复界面;- fnOS 原生安装包;- Debian/Ubuntu .deb 包;- 可从 U 盘启动的 Live ISO;- Windows 只读诊断入口和引导到 Linux/Live ISO 的安全方案;- macOS 上的案例整理、清单处理和远程连接方案。目前公开版本为 v0.1.1 prerelease,已经完成完整高级 Btrfs 工具、Web 恢复链路、fnOS 服务、真机安装/升级/回滚/卸载,以及 Live ISO 的 BIOS/UEFI 启动验收。正式使用时请从 Release 页面下载,并核对随版本提供的 SHA-256;不建议普通用户直接使用开发分支处理唯一一份原始数据。v0.1.1 Release:https://github.com/superms-lab/fnos-rescue/releases/tag/v0.1.1 Live ISO SHA-256:7da827c82676f9521f6ba2ef00561c35ad9cdc6e73ffce11a7a71f239c692248## 我也整理了一个恢复 Skill除了程序,我还整理了一个面向 Codex/AI 助手的 recover-fnos-btrfs-disks Skill。它的作用不是替用户冒险执行命令,而是约束助手始终遵守:- 源盘只读;- 禁止危险修复命令;- 修改只发生在可丢弃的 QCOW2 overlay;- 每次扫描结果必须保存;- 先验证代表性样本,再批量恢复;- 失败文件必须进入 manifest,不能悄悄跳过;- 恢复结果必须写到另一块盘;- 不把“文件名和大小正确”误判成“文件内容正确”。Skill 已随项目公开在 GitHub,适合需要让 AI 协助整理证据、生成只读命令、分析历史 root、制作失败清单和续接长时间恢复任务的用户。它不能代替硬盘镜像、专业判断或人工核对设备序列号。Skill:https://github.com/superms-lab/fnos-rescue/tree/v0.1.1/integrations/codex/recover-fnos-btrfs-disks> 下载建议:优先使用 FNOS Rescue v0.1.1 Release、SHA-256 校验文件和仓库中的公开 Skill。所有二进制与 ISO 都应来自同一版本,不要使用来源不明的转载附件。## 工具适合哪些情况比较适合:- 飞牛 Basic 单盘 Btrfs 存储空间被删除;- 硬盘能识别但 Btrfs 无法正常挂载;- UFS 能看到目录,但导出的文件打不开;- 当前 root/chunk 元数据损坏,但磁盘上可能还有历史树节点;- 多块相似故障盘需要统一记录、扫描和恢复;- 希望全过程保留日志、哈希、失败清单和续作状态。不适合直接套用:- 硬盘有严重物理故障、异响或大量读错误但尚未成像;- 加密卷但没有密钥;- 数据已经被大量新写入覆盖;- RAID/多盘池拓扑尚未确认;- 无法准确区分源盘和目标盘;- 希望在唯一原盘上直接执行 repair。## 给遇到同类问题的朋友几个建议1. 发现误删后立即停止使用 NAS,不要重建同名存储空间;2. 拍照并记录每块硬盘的槽位、序列号和容量;3. 不要把恢复文件写回原盘;4. 物理状态异常时,先做镜像,不要长时间反复扫描原盘;5. 每条命令执行前都重新确认设备序列号;6. 不要只统计“恢复了多少 GB”,还要统计可打开、通过结构验证的文件数量;7. 保存全部日志和失败清单,很多文件可以在找到新映射后单独补救;8. 如果不确定某条命令是否会写盘,先不要执行。## 最后的感受这次经历让我最深的体会是:数据恢复并不是“让文件名重新出现”,而是把目录、inode、extent、chunk 映射和真实文件内容重新对应起来,并且证明恢复出来的内容确实可用。如果这个项目和 Skill 能让后来遇到同样问题的人少走一些弯路、少在原盘上做一次危险操作,它就有价值。项目目前仍按预发布软件维护。欢迎懂 Btrfs、数据恢复、Linux、fnOS 打包或前端的朋友一起**代码、提交 Issue 和测试反馈。也欢迎遇到相似问题的朋友分享故障前后的磁盘结构,但请务必隐藏序列号、个人路径、文件名和其他隐私信息。GitHub:https://github.com/superms-lab/fnos-rescue 问题反馈:https://github.com/superms-lab/fnos-rescue/issues

收藏
送赞
分享

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则