451 lines
12 KiB
Markdown
451 lines
12 KiB
Markdown
# 数据恢复详细执行计划
|
||
|
||
## 目标
|
||
恢复 `/mnt/PoolOne/apps/youyidian-3d/uploads` 目录中被删除的数据。
|
||
|
||
## 当前状态确认
|
||
|
||
### 存储池信息
|
||
- **存储池名称**: PoolOne
|
||
- **配置类型**: raidz2(7块硬盘,可容忍2块硬盘故障)
|
||
- **存储池状态**: ONLINE(正常)
|
||
- **总容量**: 约50.5TB
|
||
- **已使用**: 约7.96TB
|
||
- **可用空间**: 约25.3TB
|
||
|
||
### 硬盘信息
|
||
7块 WDC WD80EFBX 8TB 硬盘:
|
||
1. ata-WDC_WD80EFBX-68AZZN0_VRGYN7GK-part2
|
||
2. ata-WDC_WD80EFBX-68AZZN0_VRGZW7VK-part2
|
||
3. ata-WDC_WD80EFBX-68AZZN0_VRGZT7LK-part2
|
||
4. ata-WDC_WD80EFBX-68AZZN0_VRGZVR2K-part2
|
||
5. ata-WDC_WD80EFBX-68AZZN0_VRH01V0K-part2
|
||
6. ata-WDC_WD80EFBX-68AZZN0_VRGZSHZK-part2
|
||
7. ata-WDC_WD80EFBX-68AZZN0_VRGSYK4K-part2
|
||
|
||
### uploads目录状态
|
||
- **路径**: `/mnt/PoolOne/apps/youyidian-3d/uploads`
|
||
- **当前状态**: 目录存在但为空(512字节)
|
||
- **数据丢失时间**: 2026年1月13日09:15
|
||
- **删除操作**: 由部署脚本的 `rm -rf` 或 `git clean -fd` 命令导致
|
||
|
||
### 数据集信息
|
||
- **类型**: filesystem(数据集,不是Zvol)
|
||
- **挂载点**: `/mnt/PoolOne`
|
||
- **快照状态**: 无快照可用
|
||
|
||
## 恢复方案详细步骤
|
||
|
||
## 方案1:Ubuntu设备 + ZFS存储池导入(最优先)⭐⭐⭐⭐⭐
|
||
|
||
### 前置条件检查清单
|
||
|
||
#### 硬件要求
|
||
- [ ] Ubuntu设备(Ubuntu 20.04或更高版本)
|
||
- [ ] 所有7块硬盘(必须全部连接)
|
||
- [ ] 足够的SATA接口(7个)或USB 3.0硬盘盒
|
||
- [ ] 足够的电源供应(7块8TB硬盘需要大量电源)
|
||
- [ ] **至少2TB可用空间**(用于恢复的文件,实际需要恢复的数据约1.5TB)
|
||
|
||
#### 软件要求
|
||
- [ ] Ubuntu系统已安装
|
||
- [ ] 网络连接(用于下载工具)
|
||
- [ ] root或sudo权限
|
||
|
||
### 详细执行步骤
|
||
|
||
#### 阶段1:Ubuntu环境准备
|
||
|
||
**步骤1.1:验证Ubuntu版本**
|
||
```bash
|
||
# 检查Ubuntu版本
|
||
lsb_release -a
|
||
|
||
# 要求:Ubuntu 20.04或更高版本
|
||
# 如果版本过低,需要升级或使用Live CD
|
||
```
|
||
|
||
**步骤1.2:安装ZFS工具**
|
||
```bash
|
||
# 更新软件包列表
|
||
sudo apt-get update
|
||
|
||
# 安装ZFS工具
|
||
sudo apt-get install -y zfsutils-linux
|
||
|
||
# 验证安装
|
||
zfs --version
|
||
zpool --version
|
||
|
||
# 预期输出:ZFS版本信息
|
||
```
|
||
|
||
**步骤1.3:安装数据恢复工具**
|
||
```bash
|
||
# 安装testdisk和photorec
|
||
sudo apt-get install -y testdisk
|
||
|
||
# 安装其他恢复工具
|
||
sudo apt-get install -y foremost scalpel
|
||
|
||
# 验证安装
|
||
testdisk --version
|
||
photorec --version
|
||
```
|
||
|
||
**步骤1.4:创建恢复工作目录**
|
||
```bash
|
||
# 创建工作目录
|
||
RECOVERY_DIR="/tmp/recovery_$(date +%Y%m%d_%H%M%S)"
|
||
mkdir -p "$RECOVERY_DIR"
|
||
echo "恢复目录: $RECOVERY_DIR"
|
||
|
||
# 确保有足够空间(至少100GB)
|
||
df -h /tmp
|
||
```
|
||
|
||
#### 阶段2:硬盘连接和识别
|
||
|
||
**步骤2.1:连接所有硬盘**
|
||
|
||
**选项A:直接SATA连接**
|
||
- 将7块硬盘连接到Ubuntu设备的SATA接口
|
||
- 确保电源充足(每块硬盘约10W,7块约70W)
|
||
- 开机后检查设备
|
||
|
||
**选项B:USB硬盘盒(推荐)**
|
||
- 使用USB 3.0多盘位硬盘盒
|
||
- 或使用多个单盘位USB硬盘盒
|
||
- 确保USB 3.0接口(速度要求)
|
||
|
||
**步骤2.2:识别硬盘设备**
|
||
```bash
|
||
# 查看所有块设备
|
||
lsblk
|
||
|
||
# 预期输出:应该能看到7块硬盘(sdc, sdd, sde, sdf, sdg, sdh, sdi等)
|
||
|
||
# 查看硬盘ID(匹配TrueNAS中的硬盘ID)
|
||
ls -la /dev/disk/by-id/ | grep WDC_WD80EFBX
|
||
|
||
# 预期输出:应该能看到7块硬盘的part2分区,例如:
|
||
# ata-WDC_WD80EFBX-68AZZN0_VRGYN7GK-part2 -> ../../sdc2
|
||
# ata-WDC_WD80EFBX-68AZZN0_VRGZW7VK-part2 -> ../../sdd2
|
||
# ... (共7块)
|
||
|
||
# 记录设备映射关系
|
||
ls -la /dev/disk/by-id/ | grep WDC_WD80EFBX > "$RECOVERY_DIR/disk-mapping.txt"
|
||
cat "$RECOVERY_DIR/disk-mapping.txt"
|
||
```
|
||
|
||
**步骤2.3:验证所有硬盘已连接**
|
||
```bash
|
||
# 统计匹配的硬盘数量
|
||
DISK_COUNT=$(ls -la /dev/disk/by-id/ | grep -c "WDC_WD80EFBX.*part2")
|
||
echo "找到硬盘数量: $DISK_COUNT"
|
||
|
||
# 必须等于7
|
||
if [ "$DISK_COUNT" -eq 7 ]; then
|
||
echo "✅ 所有7块硬盘已连接"
|
||
else
|
||
echo "❌ 错误: 只找到 $DISK_COUNT 块硬盘,需要7块"
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
#### 阶段3:导入ZFS存储池
|
||
|
||
**步骤3.1:查看可导入的存储池**
|
||
```bash
|
||
# 查看可导入的存储池
|
||
sudo zpool import
|
||
|
||
# 预期输出:
|
||
# pool: PoolOne
|
||
# id: 162731025200795572
|
||
# state: ONLINE
|
||
# action: The pool can be imported using its name or numeric identifier.
|
||
```
|
||
|
||
**步骤3.2:导入存储池(只读模式尝试)**
|
||
```bash
|
||
# 先尝试只读导入(如果支持)
|
||
# 注意:zpool import 默认是读写模式,但我们可以先检查
|
||
|
||
# 查看导入选项
|
||
sudo zpool import -n PoolOne
|
||
|
||
# 实际导入(使用-f强制,因为来自不同系统)
|
||
sudo zpool import -f PoolOne
|
||
|
||
# 预期输出:存储池导入成功
|
||
```
|
||
|
||
**步骤3.3:验证存储池状态**
|
||
```bash
|
||
# 检查存储池状态
|
||
sudo zpool status PoolOne
|
||
|
||
# 预期输出:
|
||
# pool: PoolOne
|
||
# state: ONLINE
|
||
# status: 所有硬盘状态为ONLINE
|
||
|
||
# 检查存储池信息
|
||
sudo zpool list PoolOne
|
||
|
||
# 查看数据集列表
|
||
sudo zfs list -o name,type,used,avail,refer,mountpoint -r PoolOne | head -20
|
||
```
|
||
|
||
**步骤3.4:确认挂载点**
|
||
```bash
|
||
# 查看挂载点
|
||
df -h | grep PoolOne
|
||
|
||
# 可能的位置:
|
||
# /PoolOne 或 /mnt/PoolOne
|
||
|
||
# 检查uploads目录
|
||
if [ -d "/PoolOne/apps/youyidian-3d/uploads" ]; then
|
||
UPLOADS_PATH="/PoolOne/apps/youyidian-3d/uploads"
|
||
elif [ -d "/mnt/PoolOne/apps/youyidian-3d/uploads" ]; then
|
||
UPLOADS_PATH="/mnt/PoolOne/apps/youyidian-3d/uploads"
|
||
else
|
||
# 查找uploads目录
|
||
UPLOADS_PATH=$(find /PoolOne /mnt/PoolOne -type d -name "uploads" -path "*/youyidian-3d/*" 2>/dev/null | head -1)
|
||
fi
|
||
|
||
echo "uploads目录路径: $UPLOADS_PATH"
|
||
```
|
||
|
||
#### 阶段4:数据状态检查和分析
|
||
|
||
**步骤4.1:检查uploads目录状态**
|
||
```bash
|
||
# 查看目录内容
|
||
ls -lah "$UPLOADS_PATH"
|
||
|
||
# 查看目录大小
|
||
du -sh "$UPLOADS_PATH"
|
||
|
||
# 统计文件数量
|
||
find "$UPLOADS_PATH" -type f 2>/dev/null | wc -l
|
||
|
||
# 查看目录的inode信息
|
||
stat "$UPLOADS_PATH"
|
||
```
|
||
|
||
**步骤4.2:查看ZFS操作历史**
|
||
```bash
|
||
# 查看存储池的操作历史
|
||
sudo zfs history PoolOne > "$RECOVERY_DIR/zfs-history-full.txt"
|
||
|
||
# 查看最近100条记录
|
||
tail -100 "$RECOVERY_DIR/zfs-history-full.txt"
|
||
|
||
# 搜索与uploads或删除相关的操作
|
||
grep -i "upload\|delete\|rm\|clean" "$RECOVERY_DIR/zfs-history-full.txt" > "$RECOVERY_DIR/zfs-history-uploads.txt"
|
||
cat "$RECOVERY_DIR/zfs-history-uploads.txt"
|
||
```
|
||
|
||
**步骤4.3:导出ZFS元数据**
|
||
```bash
|
||
# 导出ZFS标签信息
|
||
sudo zdb -l PoolOne > "$RECOVERY_DIR/zfs-label.txt" 2>&1
|
||
|
||
# 导出ZFS对象信息(可能需要较长时间)
|
||
echo "正在导出ZFS对象信息(这可能需要很长时间)..."
|
||
sudo zdb -o PoolOne > "$RECOVERY_DIR/zfs-objects.txt" 2>&1 &
|
||
|
||
# 导出事务组信息
|
||
sudo zdb -u PoolOne > "$RECOVERY_DIR/zfs-uberblock.txt" 2>&1
|
||
|
||
# 导出数据集信息
|
||
sudo zdb -d PoolOne > "$RECOVERY_DIR/zfs-dataset.txt" 2>&1
|
||
|
||
echo "元数据导出完成,文件保存在: $RECOVERY_DIR"
|
||
```
|
||
|
||
**步骤4.4:分析ZFS元数据**
|
||
```bash
|
||
# 在对象信息中搜索uploads相关的内容
|
||
if [ -f "$RECOVERY_DIR/zfs-objects.txt" ]; then
|
||
echo "搜索uploads相关的对象..."
|
||
grep -i "upload" "$RECOVERY_DIR/zfs-objects.txt" | head -50 > "$RECOVERY_DIR/zfs-objects-uploads.txt"
|
||
cat "$RECOVERY_DIR/zfs-objects-uploads.txt"
|
||
fi
|
||
|
||
# 查看事务组信息(可能包含删除操作的时间戳)
|
||
if [ -f "$RECOVERY_DIR/zfs-uberblock.txt" ]; then
|
||
echo "查看事务组信息..."
|
||
head -100 "$RECOVERY_DIR/zfs-uberblock.txt"
|
||
fi
|
||
```
|
||
|
||
#### 阶段5:尝试恢复方法
|
||
|
||
**方法5.1:ZFS调试工具深度分析**
|
||
|
||
```bash
|
||
# 查看块指针信息
|
||
sudo zdb -bb PoolOne > "$RECOVERY_DIR/zfs-blocks.txt" 2>&1
|
||
|
||
# 查看数据集树结构
|
||
sudo zdb -P -t PoolOne > "$RECOVERY_DIR/zfs-tree.txt" 2>&1
|
||
|
||
# 尝试查找已删除的对象ID
|
||
# 这需要深入分析ZFS的内部结构
|
||
```
|
||
|
||
**方法5.2:文件系统级别扫描(如果ZFS允许)**
|
||
|
||
```bash
|
||
# 注意:ZFS限制了底层访问,此方法效果有限
|
||
|
||
# 在uploads目录中使用find查找可能的残留
|
||
find "$UPLOADS_PATH" -type f -name ".*" 2>/dev/null
|
||
|
||
# 检查是否有隐藏文件
|
||
find "$UPLOADS_PATH" -type f 2>/dev/null
|
||
```
|
||
|
||
**方法5.3:底层块设备扫描(最后手段)**
|
||
|
||
```bash
|
||
# ⚠️ 警告:此操作需要导出存储池,风险较高
|
||
|
||
# 1. 导出存储池
|
||
sudo zfs unmount PoolOne
|
||
sudo zpool export PoolOne
|
||
|
||
# 2. 对每块硬盘进行扫描
|
||
# 注意:raidz2配置下,单块硬盘无法完整恢复数据
|
||
|
||
# 识别设备(从之前的记录中获取)
|
||
# 假设设备为:sdc2, sdd2, sde2, sdf2, sdg2, sdh2, sdi2
|
||
|
||
# 使用photorec扫描(交互式)
|
||
# sudo photorec /dev/sdc2
|
||
|
||
# 或使用命令行模式
|
||
# sudo photorec /log /d /tmp/recovered /cmd /dev/sdc2 partition_none,fileopt,everything,enable,search
|
||
```
|
||
|
||
## 方案2:专业ZFS恢复工具
|
||
|
||
### 工具选项
|
||
|
||
#### 选项2.1:R-Studio(商业软件)
|
||
- **支持ZFS**: 是
|
||
- **支持raidz2**: 是
|
||
- **价格**: 约$80-900(根据版本)
|
||
- **使用方法**:
|
||
1. 在Ubuntu设备上安装R-Studio
|
||
2. 导入ZFS存储池
|
||
3. 使用ZFS恢复功能
|
||
|
||
#### 选项2.2:UFS Explorer(商业软件)
|
||
- **支持ZFS**: 是
|
||
- **支持raidz2**: 是
|
||
- **价格**: 约$50-500
|
||
- **使用方法**: 类似R-Studio
|
||
|
||
#### 选项2.3:专业数据恢复服务
|
||
- **优势**: 专业工具和技术
|
||
- **劣势**: 成本高(通常数万元)
|
||
- **适用**: 数据非常重要且预算充足
|
||
|
||
## 方案3:ZFS元数据手动分析(高级)
|
||
|
||
### 前提条件
|
||
- 深入理解ZFS文件系统结构
|
||
- 熟悉ZFS元数据格式
|
||
- 编程能力(可能需要编写脚本)
|
||
|
||
### 步骤概述
|
||
1. 导出所有ZFS元数据
|
||
2. 分析对象ID映射
|
||
3. 查找已删除文件的元数据
|
||
4. 重建目录结构
|
||
5. 提取数据块
|
||
|
||
## 不确定因素排查清单
|
||
|
||
### ✅ 已确认的信息
|
||
- [x] 存储池名称:PoolOne
|
||
- [x] 配置类型:raidz2(7块硬盘)
|
||
- [x] 存储池状态:ONLINE
|
||
- [x] uploads目录路径:/mnt/PoolOne/apps/youyidian-3d/uploads
|
||
- [x] 数据集类型:filesystem(不是Zvol)
|
||
- [x] 快照状态:无快照
|
||
- [x] 硬盘型号:WDC WD80EFBX 8TB
|
||
- [x] 数据丢失时间:2026年1月13日09:15
|
||
|
||
### ❓ 需要确认的信息
|
||
- [ ] Ubuntu设备的具体型号和配置
|
||
- [ ] Ubuntu设备的SATA接口数量
|
||
- [ ] 是否有USB硬盘盒可用
|
||
- [ ] Ubuntu设备的电源容量
|
||
- [ ] Ubuntu系统版本
|
||
- [ ] 是否有足够的存储空间(至少100GB)
|
||
- [ ] ZFS版本兼容性(TrueNAS使用的ZFS版本 vs Ubuntu的ZFS版本)
|
||
- [ ] 存储池导入后是否会自动挂载
|
||
- [ ] 存储池导入后的挂载点路径
|
||
|
||
### ⚠️ 风险和限制
|
||
- [ ] ZFS删除机制:ZFS不提供原生的undelete功能
|
||
- [ ] raidz2配置:数据条带化分布,需要所有硬盘
|
||
- [ ] 时间窗口:删除后时间越长,恢复可能性越低
|
||
- [ ] 写入操作:如果删除后有大量写入,数据可能已被覆盖
|
||
- [ ] ZFS版本兼容性:不同版本的ZFS可能有兼容性问题
|
||
|
||
## 执行优先级
|
||
|
||
### 第一优先级(立即执行)
|
||
1. ✅ **准备Ubuntu设备**
|
||
2. ✅ **连接所有7块硬盘**
|
||
3. ✅ **导入ZFS存储池**
|
||
4. ✅ **检查数据状态**
|
||
5. ✅ **查看ZFS历史记录**
|
||
|
||
### 第二优先级(深度分析)
|
||
1. ✅ **导出ZFS元数据**
|
||
2. ✅ **分析ZFS历史记录**
|
||
3. ✅ **搜索uploads相关对象**
|
||
|
||
### 第三优先级(尝试恢复)
|
||
1. ✅ **使用ZFS调试工具**
|
||
2. ✅ **分析ZFS元数据**
|
||
3. ✅ **尝试手动恢复**
|
||
|
||
### 第四优先级(最后手段)
|
||
1. ⚠️ **底层块设备扫描**(风险高)
|
||
2. ⚠️ **专业数据恢复工具/服务**
|
||
|
||
## 成功概率评估
|
||
|
||
| 方案 | 成功概率 | 原因 |
|
||
|------|---------|------|
|
||
| ZFS历史记录分析 | 10% | ZFS历史记录可能包含删除操作的线索,但无法直接恢复数据 |
|
||
| ZFS元数据分析 | 20% | 需要深入理解ZFS结构,可能找到已删除对象的元数据 |
|
||
| 底层块设备扫描 | 5% | raidz2配置和ZFS限制使恢复非常困难 |
|
||
| 专业工具/服务 | 60-80% | 专业工具和技术,但成本高 |
|
||
|
||
## 关键检查点
|
||
|
||
在执行每个阶段后,需要检查:
|
||
1. ✅ 所有硬盘是否正常识别
|
||
2. ✅ 存储池是否成功导入
|
||
3. ✅ uploads目录是否存在
|
||
4. ✅ ZFS历史记录是否包含有用信息
|
||
5. ✅ ZFS元数据是否成功导出
|
||
6. ✅ 是否有任何恢复线索
|
||
|
||
## 下一步行动
|
||
|
||
1. **确认Ubuntu设备准备情况**
|
||
2. **确认所有7块硬盘可以连接**
|
||
3. **开始执行方案1的阶段1和阶段2**
|
||
4. **根据检查结果决定后续步骤**
|