数据恢复开源项目全景:从手滑删文件到硬盘嗝屁的救命工具箱

数据恢复开源项目全景 · 救命工具箱 :root { --paper: #fbfaf7; --paper-2:...

数据恢复开源项目全景 · 救命工具箱 :root { –paper: #fbfaf7; –paper-2: #f3f1ea; –ink: #1c1b18; –ink-soft: #4a4742; –ink-faint: #8a857c; –line: #e2ddd2; –recover: #1f7a5c; /* 复原绿 */ –recover-soft: #e7f1ec; –warn: #b8742a; /* 警示琥珀 */ –warn-soft: #f7ecdd; –danger: #b4453a; –code-bg: #1e1e1e; –code-ink: #e6e6e6; –maxw: 860px; –serif: Georgia, “Songti SC”, “STSong”, “SimSun”, serif; –sans: -apple-system, BlinkMacSystemFont, “PingFang SC”, “Microsoft YaHei”, “Hiragino Sans GB”, sans-serif; –mono: “SF Mono”, “JetBrains Mono”, “Fira Code”, Consolas, Menlo, monospace; } * { box-sizing: border-box; } html { scroll-behavior: smooth; } body { margin: 0; background: var(–paper); color: var(–ink); font-family: var(–sans); font-size: 17px; line-height: 1.78; -webkit-font-smoothing: antialiased; } .wrap { max-width: 1180px; margin: 0 auto; display: flex; gap: 48px; padding: 0 28px; } /* ===== 侧栏 TOC ===== */ aside { position: sticky; top: 0; align-self: flex-start; width: 250px; flex: 0 0 250px; height: 100vh; overflow-y: auto; padding: 34px 0 60px; border-right: 1px solid var(–line); font-size: 14px; } aside .toc-title { font-family: var(–serif); font-size: 13px; letter-spacing: .14em; text-transform: uppercase; color: var(–ink-faint); margin: 0 0 16px; padding-left: 14px; } aside a { display: block; color: var(–ink-soft); text-decoration: none; padding: 6px 14px; border-left: 2px solid transparent; line-height: 1.45; transition: all .15s ease; } aside a:hover { color: var(–ink); background: var(–paper-2); } aside a.active { color: var(–recover); border-left-color: var(–recover); font-weight: 600; } aside a.sub { padding-left: 28px; font-size: 13px; } /* ===== 主文 ===== */ main { flex: 1 1 auto; min-width: 0; max-width: var(–maxw); padding: 40px 0 100px; } header.hero { border-bottom: 3px double var(–line); padding-bottom: 30px; margin-bottom: 38px; } .hero-kicker { display: inline-flex; align-items: center; gap: 9px; font-size: 13px; letter-spacing: .1em; color: var(–recover); font-weight: 600; margin-bottom: 14px; text-transform: uppercase; } .hero-kicker svg { width: 22px; height: 22px; } h1 { font-family: var(–serif); font-weight: 700; font-size: 38px; line-height: 1.25; margin: 0 0 14px; letter-spacing: -.01em; } .hero-sub { font-size: 16px; color: var(–ink-soft); margin: 0; font-style: italic; } .lede { margin-top: 22px; padding: 18px 22px; background: var(–paper-2); border-left: 4px solid var(–recover); border-radius: 4px; font-size: 16px; color: var(–ink-soft); } .lede b { color: var(–ink); } h2 { font-family: var(–serif); font-size: 27px; font-weight: 700; margin: 56px 0 8px; padding-top: 18px; letter-spacing: -.01em; } h2 .num { color: var(–recover); font-style: italic; margin-right: 10px; } h3 { font-size: 19px; font-weight: 700; margin: 34px 0 6px; color: var(–ink); } h3 .tag { font-family: var(–mono); font-size: 12px; font-weight: 600; color: var(–recover); background: var(–recover-soft); padding: 2px 8px; border-radius: 4px; margin-right: 8px; vertical-align: 1px; } p { margin: 14px 0; } a.ref { color: var(–recover); text-decoration: none; border-bottom: 1px dotted var(–recover); } code { font-family: var(–mono); font-size: .88em; background: var(–paper-2); padding: 2px 6px; border-radius: 4px; color: #8a3b1f; } strong { color: var(–ink); } /* 原理小抄卡片 */ .cheat { background: var(–recover-soft); border: 1px solid #cfe3da; border-radius: 8px; padding: 16px 20px; margin: 18px 0; } .cheat h4 { margin: 0 0 8px; font-size: 15px; color: var(–recover); letter-spacing: .02em; } .cheat p { margin: 6px 0; font-size: 15.5px; } .callout { border-radius: 8px; padding: 14px 18px; margin: 18px 0; font-size: 15.5px; border: 1px solid; display: flex; gap: 12px; align-items: flex-start; } .callout .ico { font-weight: 700; font-family: var(–mono); flex: 0 0 auto; } .callout.warn { background: var(–warn-soft); border-color: #ecd2b0; color: #6e4517; } .callout.warn .ico { color: var(–warn); } .callout.danger { background: #f6e6e3; border-color: #e7c4bd; color: #7a2c24; } .callout.danger .ico { color: var(–danger); } /* 表格 */ .table-scroll { overflow-x: auto; margin: 20px 0; } table { border-collapse: collapse; width: 100%; font-size: 14.5px; min-width: 560px; } thead th { background: var(–ink); color: #f4f1e9; text-align: left; padding: 11px 13px; font-weight: 600; font-size: 13.5px; letter-spacing: .02em; white-space: nowrap; } tbody td { padding: 10px 13px; border-bottom: 1px solid var(–line); vertical-align: top; } tbody tr:nth-child(even) { background: var(–paper-2); } tbody tr:hover { background: var(–recover-soft); } td .tool { font-weight: 700; color: var(–recover); white-space: nowrap; } /* 代码块 */ .code-block { position: relative; margin: 18px 0; } .code-block pre { background: var(–code-bg); color: var(–code-ink); padding: 18px 20px; border-radius: 8px; overflow-x: auto; font-family: var(–mono); font-size: 13.5px; line-height: 1.7; margin: 0; } .code-block .copy { position: absolute; top: 10px; right: 10px; background: rgba(255,255,255,.12); color: #ddd; border: none; font-size: 12px; padding: 4px 10px; border-radius: 5px; cursor: pointer; font-family: var(–sans); } .code-block .copy:hover { background: rgba(255,255,255,.22); } .code-block .c { color: #7f8c8c; } /* 注释 */ .code-block .o { color: #f0a868; } /* 命令 */ .code-block .f { color: #8fd6b4; } /* 文件/路径 */ /* 决策树 */ .tree { margin: 22px 0; display: flex; flex-direction: column; gap: 0; } .tree-row { display: grid; grid-template-columns: 1fr 44px 1fr; align-items: stretch; gap: 0; } .tree-trigger, .tree-tool { padding: 13px 16px; border-radius: 8px; font-size: 14.5px; } .tree-trigger { background: var(–paper-2); border: 1px solid var(–line); } .tree-tool { background: var(–recover-soft); border: 1px solid #cfe3da; font-weight: 600; color: var(–recover); } .tree-arrow { display: flex; align-items: center; justify-content: center; color: var(–ink-faint); font-size: 18px; font-family: var(–mono); } /* 分层图 */ .stack { margin: 24px 0; } .stack-row { display: flex; align-items: center; gap: 16px; padding: 14px 18px; border-radius: 8px; margin-bottom: 8px; color: #fff; font-weight: 600; } .stack-row .lv { font-family: var(–mono); font-size: 13px; opacity: .8; flex: 0 0 36px; } .stack-row .nm { font-size: 16px; } .stack-row .ds { font-weight: 400; font-size: 13.5px; opacity: .92; margin-left: auto; text-align: right; } /* 收口口诀 */ blockquote.closing { margin: 30px 0; padding: 20px 24px; background: var(–ink); color: #f1ede2; border-radius: 8px; font-family: var(–serif); font-size: 18px; line-height: 1.85; border-left: 5px solid var(–recover); } blockquote.closing p { margin: 6px 0; } footer.refs { margin-top: 50px; padding-top: 24px; border-top: 1px solid var(–line); font-size: 13.5px; color: var(–ink-faint); } footer.refs h3 { color: var(–ink-soft); font-size: 15px; } footer.refs ul { padding-left: 20px; margin: 8px 0; } footer.refs li { margin: 5px 0; } .colophon { margin-top: 30px; font-size: 12px; color: var(–ink-faint); text-align: center; } /* 移动端 */ .menu-btn { display: none; } @media (max-width: 920px) { .wrap { display: block; padding: 0 18px; } aside { position: fixed; top: 0; left: 0; z-index: 50; width: 260px; height: 100vh; background: var(–paper); transform: translateX(-100%); transition: transform .25s ease; box-shadow: 2px 0 12px rgba(0,0,0,.12); } aside.open { transform: translateX(0); } main { max-width: 100%; padding: 70px 0 80px; } .menu-btn { display: block; position: fixed; top: 12px; left: 12px; z-index: 60; background: var(–ink); color: #fff; border: none; border-radius: 6px; padding: 9px 14px; font-size: 14px; cursor: pointer; font-family: var(–sans); } h1 { font-size: 30px; } .tree-row { grid-template-columns: 1fr; gap: 6px; margin-bottom: 10px; } .tree-arrow { transform: rotate(90deg); height: 22px; } }

目录 · Contents

一、三件事先搞懂 二、工具分类矩阵 2.1 TestDisk 2.2 文件雕刻 2.3 Ext 反删除 2.4 故障盘镜像 2.5 取证平台 2.6 备份即恢复 2.7 DMDE 三、选型决策树 四、总对比矩阵 五、避坑清单 六、最小实战流程 七、收口口诀 参考来源 开源数据恢复 · 技术综述

数据恢复开源项目全景:
从手滑删文件到硬盘嗝屁的救命工具箱

一份基于实测与社区共识的中文综述。写给那个刚 rm -rf 完、或 SD 卡插电脑提示「需要格式化」的人。

先说个真事。某人十年照片、音乐、文档全压在一块突然罢工的盘上,没备份。他原话:「你总觉得这事不会轮到自己,直到它轮到你。」数据恢复不是魔法。它吃的是「文件系统怎么干活」这碗饭。你越早懂原理,越早停手,东西越拿得回来。

下面先立个总纲:数据恢复不是一把万能钥匙。它是一整套按「灾难类型」分层的工具箱——用错层,白忙活。

三件事先搞懂(原理小抄)

① 删除 ≠ 消失

在 Ext4、NTFS、FAT 这些文件系统里,「删除」大多只是把目录项打个「这块空间可用了」的标。文件的实际字节,还躺在盘上。只要没人往这块地方写新东西,数据就还在。所以「刚删完、立刻停手」能救回大部分——这是真的,不是安慰。

② 格式化 ≠ 清空

所谓快速格式化,多数只重建文件系统的结构(分区表、根目录),没把每个扇区擦一遍。格式化之后的盘,常常还能找回原文件。前提是:别往里拷新东西。

③ 雕刻(carving)是个啥?

文件系统本身碎了、或者盘干脆不认了,普通工具没辙。换思路:跳过文件系统,直接扫原始扇区,按「文件头 + 文件尾」的特征签名(signature)把一段段数据抠出来。PhotoRec 干的就是这个。代价明摆着:抠出来的文件,通常没原名、没目录,一堆 f12345.jpg 等你回去一张张认。

!
两个要命的例外,记牢:
SSD 的 TRIM。固态盘为了性能和寿命,删除后会发 TRIM 命令,把数据块真擦掉。所以 SSD 上「删了再恢复」的难度,比机械盘高一个数量级。盘一出事,马上断电、别再读写
覆写即绝路。任何新写入——连系统偷偷往盘里写日志、建缓存都算——都可能盖掉你要救的数据。恢复第一铁律在此:结果写到另一块盘,绝不回写源盘。

工具分类矩阵,逐个捋

数据恢复这行,按「灾难落在哪一层」分工具。下面这张分层图,先立个总览:

L5备份即恢复Restic / Borg / Kopia — 治本,别等丢了才救
L4取证级平台Autopsy + TSK — 司法鉴定、时间线、系统分析
L3故障盘镜像ddrescue / HDDSuperClone — 先拷后救,对付坏道
L2文件雕刻PhotoRec / Scalpel — 文件系统碎了,按签名抠
L1反删除 / 修结构extundelete / TestDisk — 名字目录都还在时首选

2.1分区与文件系统修复:TestDisk

CGSecurity 出品,GPL,全平台(Win/mac/Linux/DOS/BSD)。它专治「分区没了、盘不认、引导扇区坏了」这类结构性灾难。

  • 重建分区表、修 FAT 表、修 NTFS 引导扇区,它都行;
  • FAT、exFAT、NTFS、Ext2/3/4、HFS+、APFS……一大票文件系统通吃;
  • 纯命令行 TUI,对新手不友好。可它是这行的老祖宗,救过的分区数不清。

一句话点破:TestDisk 救「容器」,PhotoRec 救「容器里的东西」。容器修好,文件名、目录结构都还在;容器碎了,只能上雕刻、认命丢名字。

2.2文件雕刻(按签名):PhotoRec / Foremost / Scalpel / Bulk Extractor / Binwalk

  • PhotoRec(CGSecurity,GPL,跟 TestDisk 打包发):认 480+ 种格式,无视文件系统。相机卡、U 盘、格式化盘首选。缺点前面说了——不保留文件名。有 QPhotoRec 图形前端可救急。
  • Foremost:老牌签名雕刻器,配置在 /etc/foremost.conf,按需取消注释启用某类文件。轻。
  • Scalpel:Foremost 的瘦身增强版,更省资源、可配项更细,配置在 /etc/scalpel/scalpel.conf。面对几 TB 大盘,限定文件类型能明显提速。
  • Bulk Extractor(simsong 维护,v2.1.1 于 2024-04 发):不走寻常路。它并行跑多个扫描器,专抠网络痕迹——URL、域名、IP、MAC、邮箱、pcap 片段。取证、安全响应常用,结果还能转 JSON 喂 SIEM。
  • Binwalk:盯的是固件和二进制里的「内嵌内容」,靠 libmagic 的签名库识别嵌进去的文件系统、证书、代码。
Binwalk ≤ 2.3.3 有路径穿越漏洞(CVE-2022-4510)。分析不可信样本前,要么升级,要么丢容器里跑。

2.3Ext 系反删除:extundelete / ext4magic

你用 Linux 的 Ext3/Ext4,而且是「刚误删某个文件」——这是首选。它借文件系统的日志(journal)找回文件,连原文件名和路径都还原得出来。这一点,把 PhotoRec 按地上摩擦。

# 在卸载的盘,或只读镜像上操作
extundelete /dev/sdX --restore-all

前提得说清:日志里的元数据得还在,没被覆盖。还有个 ext4magic,本事类似,但早不维护了。能用 extundelete 就别碰它。

2.4故障盘镜像:先 copy 再抢救

盘有坏道、读一会儿就卡死?千万别直接在坏盘上跑恢复工具。正路是:先用镜像工具把「还能读的部分」整盘拷出来,再对镜像施救。

  • GNU ddrescue(Debian 系包名 gddrescue,GNU 项目,2025 还在更):坏道处理的标杆。它用 mapfile 记每个扇区状态,第一遍跳过坏区快速捞 healthy 数据,第二遍对坏区有限重试。断点续拷也支持。
sudo ddrescue -f -n /dev/sdX suspect.img suspect.log   # 第一遍:跳过坏道
sudo ddrescue -d -r3 /dev/sdX suspect.img suspect.log  # 第二遍:坏区重试3次
  • Clonezilla:全平台磁盘/分区克隆,图形界面,新手友好。坑在这:救援模式(rescue-mode)遇坏扇区是直接丢、不重试。比 ddrescue 多遍策略快,但也更糙,可能漏数据。健康盘整盘克隆/备份用它;奄奄一息的盘,别。
  • HDDSuperClone / OpenSuperClone:Linux 下、开源、专为坏盘设计的克隆器(HDDSuperClone 已 fork 成 OpenSuperClone)。它懂机械盘脾气——先易后难、跳过坏区、回头再啃硬骨头,还能配合电源周期化处理掉链子的盘。专业恢复圈常备。
  • 顺带一句最基础的 dd:扇区对扇区拷贝,完全不处理坏道,只配健康盘。坏盘用 dd,一个卡住的扇区能把拷贝拖到十几个小时。

2.5取证级平台:The Sleuth Kit + Autopsy

  • The Sleuth Kit(TSK):C 库加一堆命令行工具,GPL/CPL/IPL 多协议。能解析 NTFS、FAT/ExFAT、UFS、Ext2-4、HFS、ISO 9660、YAFFS2,吃 raw(dd)、E01、AFF 镜像。底层工具 fls(列文件名)、icatmactime(时间线)是取证基本功。2026-04 出了 4.15.0。
  • Autopsy:TSK 之上的图形取证平台,java/Python 插件架构。4.23.0(2026-04)已带 MCP Server;≥4.21 重构了基于 SleuthKit v4.13 的雕刻模块,TB 级镜像更快、多核并行。还给了 autopsycli 命令行,能写进 CI/CD 跑批处理。

这两样是「司法鉴定级」。普通人 TestDisk/PhotoRec 够了;要系统化分析一块镜像、出时间线、抠删除文件,它们是正宫。

2.6备份即恢复(治本):别等丢了才救

恢复工具是灭火器,备份才是防火门。以下全开源、可自托管:

工具定位亮点软肋
Restic通用、跨平台端到端加密、去重、S3/B2/Azure/SFTP 多后端;~2.69 万 star,备份 120–160 MB/s内存偏高(100–200MB),无原生 Windows VSS
BorgBackupLinux/mac 性能王去重率 70–85%、备份 180–220 MB/s、FUSE 挂载当文件系统浏览、认证加密无原生 Windows 客户端(靠 WSL),云存储得 rclone/borgmatic 包一层
Kopia现代、GUI 友好恢复最快 200–250 MB/s、Web UI、AES-256/ChaCha20v1.x 有仓库损坏报告,关键数据先观望
Duplicati新手 GUI 派Web 界面、AES 加密、调度、多后端大数据集慢,本地库偶尔要重建
UrBackup局域网镜像+文件服务端-客户端、持续备份、Web 监控偏小企业/家庭局域网
Amanda / Bacula / Bareos企业级目录化、磁带/云/磁盘、可横扩配置重,学习曲线陡
Proxmox Backup Server虚拟化VM/容器增量备份、去重、Web UI仅 Debian 系,锁 Proxmox VE 生态
rsync极简镜像增量同步,零依赖无版本管理、无加密(得自配)
黄金法则 3-2-1:3 份副本、2 种介质、1 份离线/异地。再加一条现代铁律——不可变性(immutability):用支持 S3 Object Lock 的存储(Backblaze B2、Wasabi)把备份锁住,勒索软件也删不动。
更狠的一条:备份不测 = 没备。每季度挑个随机文件真恢复一次,步骤写下来。

2.7非开源但值得提一句:DMDE

DMDE(DM Disk Editor)是免费软件,不开源。可它太能打了,不提对不起读者:免费版每次能恢复 4000 个文件、无限次;自带 RAID 重建(RAID-0/1/4/5/6/JBOD)、十六进制编辑器、分区管理、坏道克隆。跨 Windows/mac/Linux/DOS。软肋是界面复古、学习曲线陡、RAW 照片预览弱。它是「技术员工具箱」,不是「小白救星」。开源圈里能正面刚它 RAID 能力的,不多。

选型决策树(按灾难对号入座)

盘不认 / 分区消失 / 引导坏了
TestDisk(修结构,名字目录都保住)
刚在 Linux(Ext3/4) 误删某个文件
extundelete(连名字一起还原,前提:日志没被盖)
格式化了 / 显示 RAW / 相机 SD 卡 / U 盘
PhotoRec(或 Scalpel/Foremost 限速)
认命:文件名多半没了
盘有坏道、读着读着卡死
ddrescue 先两遍镜像 → 再对镜像跑上面任意工具
(专业坏盘 → HDDSuperClone/OpenSuperClone)
要抠网络痕迹 / 固件里藏的文件
Bulk Extractor(网络痕迹)/ Binwalk(固件内嵌)
司法鉴定级、要时间线、要系统分析
Autopsy + The Sleuth Kit
不想再经历一次
Restic 或 BorgBackup + 3-2-1 + 定期演练恢复

总对比矩阵

工具类别平台开源协议保留文件名一句话
TestDisk分区/结构修复全平台GPL修结构,非单文件救「容器」的老祖宗
PhotoRec文件雕刻全平台GPL480+ 格式、无视文件系统
Foremost文件雕刻Linux自由软件老牌签名雕刻
Scalpel文件雕刻Linux自由软件更省、更可配
Bulk Extractor取证雕刻全平台自由软件专抠网络/邮件痕迹
Binwalk固件分析全平台MIT固件内嵌提取(注意 CVE)
extundeleteExt 反删除LinuxGPL用日志还原名字路径
GNU ddrescue故障盘镜像LinuxGPL整盘镜像坏道多遍、可续拷
Clonezilla磁盘克隆全平台GPL整盘/分区图形化,救援模式不重试坏道
HDDSuperClone故障盘克隆Linux开源(GPL)整盘镜像专为坏盘,专业圈常用
The Sleuth Kit取证库/CLI全平台GPL/CPL/IPL视情况文件系统级底层分析
Autopsy取证平台 GUI全平台GPL视情况TSK 的图形壳,4.23.0
Restic备份全平台BSD-2备份逻辑端到端加密、云原生
BorgBackup备份Linux/macBSD备份逻辑去重性能王、FUSE 挂载
Kopia备份全平台Apache-2备份逻辑GUI 友好、恢复最快
Duplicati备份全平台LGPL/MIT备份逻辑Web UI 新手派
UrBackup备份Win/Linux自由软件备份逻辑镜像+文件、局域网
Bacula/Bareos企业备份全平台AGPL备份逻辑目录化、可扩展
DMDE综合恢复全平台闭源(免费软件)RAID/十六进制强,非 OSS

避坑与最佳实践(血泪清单)

  1. 立刻停用源盘。拔下来、只读挂载、或做镜像。任何写入都是往伤口撒盐。
  2. 先镜像,后操作。尤其坏盘,先用 ddrescue/HDDSuperClone 拷一份,所有恢复都在镜像上做。
  3. 恢复结果写别盘。永远输出到第二块盘/网络存储,绝不回写源盘。
  4. SSD 见 TRIM 即凉。固态盘删除后别抱太大希望,时间就是数据。
  5. extundelete 要日志在。文件系统被覆盖写入,这招失效,转 PhotoRec。
  6. Binwalk 升过 2.3.3。否则分析不可信样本有路径穿越风险。
  7. 物理损坏别自己开盖。硬盘开盘要无尘间,灰尘颗粒比坏道更致命;直接送专业恢复(DriveSavers、Ontrack 之类,报价 $500 起)。
  8. 备份不测等于没备。季度演练一次真恢复,写清步骤。

最小实战流程(命令行示范)

# ① 先给快挂的盘做镜像(两遍法)
sudo ddrescue -f -n /dev/sdX suspect.img suspect.log
sudo ddrescue -d -r3 /dev/sdX suspect.img suspect.log

# ② 对镜像跑 PhotoRec 雕刻(限定类型提速)
photorec /dev/sdX /restore /d /mnt/recovery/ /f jpg,png,pdf,doc,docx,xlsx

# ③ 若是分区丢了,用 TestDisk 修结构
sudo testdisk /dev/sdX

收口:选型速记口诀

结构坏了找 TestDisk,名字丢了靠 extundelete;

格式化与 RAW,PhotoRec 顶上;坏道先 ddrescue 镜像;

取证上 Autopsy,固件用 Binwalk;

真想不丢,Restic/Borg 加 3-2-1,备份还得分季节演练。

数据恢复是门「和时间赛跑、与覆写为敌」的手艺。工具全开源免费,贵的从来不是软件,是你停手的那一秒决断

参考来源

  • CGSecurity — TestDisk & PhotoRec 官方文档与下载(cgsecurity.org)
  • GNU ddrescue — GNU Savannah 项目页(含多遍救援指南)
  • The Sleuth Kit / Autopsy — sleuthkit.org(4.15.0 / 4.23.0 发布说明)
  • HackTricks — File/Data Carving & Recovery Tools(含 awesome-datarecovery 清单指引)
  • Bulk Extractor — github.com/simsong/bulk_extractor(v2.1.1,2024-04)
  • Binwalk — CVE-2022-4510 路径穿越公告(≤2.3.3 受影响)
  • Restic / BorgBackup / Kopia / Duplicati / UrBackup / Bacula / Bareos — 各项目官网与 GitHub
  • DMDE — dmde.com(免费软件,非开源,RAID/十六进制恢复评测)
  • HDDSuperClone / OpenSuperClone — Linux 开源坏盘克隆工具(Tom’s Hardware 数据恢复版块讨论)
  • 3-2-1 备份法则与 S3 Object Lock 不可变备份 — 自托管社区实践共识
  • Clonezilla 救援模式坏道处理差异 — 工业/自托管技术博客实测对比

本文由 deep-research 检索 · deai-rewrite 去 AI 味 · beautiful-article 成篇 · 单文件 HTML 可离线打开

// 复制按钮 document.querySelectorAll(‘.code-block .copy’).forEach(function(btn){ btn.addEventListener(‘click’, function(){ var code = btn.parentElement.querySelector(‘pre’).innerText; navigator.clipboard.writeText(code).then(function(){ btn.textContent = ‘已复制’; setTimeout(function(){ btn.textContent = ‘复制’; }, 1400); }); }); }); // 目录高亮 var links = Array.prototype.slice.call(document.querySelectorAll(‘#toc a’)); var sections = links.map(function(a){ return document.querySelector(a.getAttribute(‘href’)); }); var io = new IntersectionObserver(function(entries){ entries.forEach(function(e){ if(e.isIntersecting){ var id = ‘#’ + e.target.id; links.forEach(function(l){ l.classList.toggle(‘active’, l.getAttribute(‘href’) === id); }); } }); }, { rootMargin: ‘-10% 0px -75% 0px’, threshold: 0 }); sections.forEach(function(s){ if(s) io.observe(s); }); // 移动端目录 var menuBtn = document.querySelector(‘.menu-btn’); var toc = document.getElementById(‘toc’); menuBtn.addEventListener(‘click’, function(){ toc.classList.toggle(‘open’); }); toc.querySelectorAll(‘a’).forEach(function(a){ a.addEventListener(‘click’, function(){ toc.classList.remove(‘open’); }); });

发表回复

人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 借一步网 🐾 智柴网 沪ICP备2024052574号-1