暗色模式

dd 命令:从磁盘克隆到数据备份的完整指南

技术教程
2026-08-18
6
0

dd 命令:从磁盘克隆到数据备份的完整指南

本文要点
  • dd 是 Linux 的「比特级」数据复制工具,按块读写、绕过文件系统,可备份分区/整块磁盘甚至引导区。
  • 核心只有三个参数:if=(来源)、of=(目标)、bs=(块大小),支持countseekconv 等精细控制。
  • 文件备份后可用 md5sum 校验一致性;磁盘克隆后用 cmp 逐字节对比。
  • 配合 gzip/`gunzip` 可用 dd | gzip 生成压缩镜像并解压恢复。
  • dd危险命令,if/of 写反会直接覆盖数据,操作前务必确认设备名。

dd 命令是 Linux 运维中一个「老而弥坚」的工具。它没有华丽的界面,也没有复杂的交互,但几乎所有涉及按字节复制的工作——从备份一个分区、克隆整块磁盘,到生成固定大小的测试文件——都离不开它。

cprsync 这类按「文件」操作的工具不同,dd 直接读取设备或文件的每一个字节,不管里面装的是什么文件系统、什么格式。正是这种「低层」特性,让它在磁盘克隆、系统迁移、镜像制作等场景下无可替代。

本文将用真实命令逐步讲解 dd 的常用姿势:文件备份与校验、磁盘级克隆、压缩镜像与恢复,并指出最容易踩的坑。

理解 dd 的工作原理

dd 的名字来自「Data Description」,它做的事情可以概括为一句话:if(input file,输入文件)读取数据,写入 of(output file,输出文件),中间以 bs(block size,块大小)为单位搬运。

if=来源  →   [按 bs 大小的块读取]  →  of=目标

关键在于,这里的「文件」是一个广义概念。在 Linux 里,一切都可被当作文件:普通文件、设备节点(/dev/sda/dev/vda)、伪设备(/dev/zero 无限输出零、/dev/urandom 输出随机数)、甚至 /dev/null(黑洞)。

所以 dd 能干的事情远比「复制」多:

  • /dev/zero 读 → 生成全零文件(占位、测试、预分配磁盘空间)
  • /dev/urandom 读 → 生成随机数据
  • /dev/sda 读 → 备份整块磁盘
  • 写到 /dev/vda → 恢复/写入磁盘

常用参数速查

参数作用
if=输入文件或设备
of=输出文件或设备
bs=一次读写的块大小,如 bs=1M
count=复制多少块(count=N 即复制 N 个块)
seek=在输出文件中跳过多少块再写
skip=从输入文件跳过多少块再读
conv=转换,常用 notrunc(不截断输出)、fsync(写完落盘)
status=输出级别:none 静默、progress 显示实时进度

块大小 bs 很有讲究。太小(如 bs=512)会反复进入内核,速度慢;太大(如 bs=64M)读写次数少、速度通常更快。实践中测速调优是常见用法。

文件备份:创建文件、复制与校验

dd 最基础的用法是复制。我们先创建一个随机数据文件作为「原始文件」,再用 status=none 关掉多余输出,最后用 md5sum 校验两份文件内容是否完全一致:

# 1. 生成一个 4MB 的随机数据文件作为"原始数据"
dd if=/dev/urandom of=/root/sample.bin bs=1M count=4 status=none

# 2. 查看生成的文件
ls -lh /root/sample.bin

# 3. 用 dd 把它复制成备份(块大小 2M)
dd if=/root/sample.bin of=/root/backup.bin bs=2M status=none

# 4. 校验两份文件内容一致
md5sum /root/sample.bin /root/backup.bin

dd 文件备份与 MD5 校验

上面截图里可以看到,/root/backup.bin/root/sample.bin 的 MD5 值完全一致(f7c94b3f...),说明字节级复制没有发生任何改变。md5sum 的作用就是给你一把「内容指纹」,任何一位不同都会让哈希值大变。

小提示md5sum 出现「两个文件哈希一样」只能说明内容一致;若要更严格更快,也可用 sha256sum。日常备份核对用 md5 已经足够。

用 count 生成指定大小文件

count=N 让你精确控制「复制几个块」。结合块大小,就能生成任意尺寸的文件。这在预分配空间制作测试文件模拟网络慢速时非常常用:

# 生成一个 100MB 的全零文件(占位 / 测试用)
dd if=/dev/zero of=/tmp/bigfile bs=1M count=100

# 生成一个 512MB 的随机文件(不适合大文件,会慢)
dd if=/dev/urandom of=/tmp/rand bs=1M count=512

磁盘级克隆:整块盘备份与对拷

dd 真正不可替代的场景是磁盘克隆——把一整块磁盘或分区原样复制成镜像文件,或者直接对拷到另一块盘。文件系统、分区表、引导扇区,全部原封不动。

为了在演示服务器上安全地展示,我们用 dd 先造一个「假磁盘」镜像文件,再把它克隆成第二份,并用 cmp 逐字节校验:

# 1. 创建一个 8MB 的磁盘镜像(模拟一块"磁盘")
dd if=/dev/zero of=/root/disk_a.img bs=1M count=8 status=none

# 2. 给它格式化成 ext4(这样才像一块有文件系统的真盘)
mkfs.ext4 -q /root/disk_a.img

# 3. 用 dd 把它整体克隆成 disk_b.img(块大小 4M)
dd if=/root/disk_a.img of=/root/disk_b.img bs=4M status=none

# 4. cmp 逐字节比较两个文件,无差异则返回 0 并输出成功提示
cmp /root/disk_a.img /root/disk_b.img && echo '克隆成功: 两个磁盘完全一致'

# 5. 查看文件大小
ls -lh /root/disk_a.img /root/disk_b.img

dd 磁盘级克隆与校验

截图里可见 disk_a.imgdisk_b.img 都是 8.0M,cmp 没有输出(说明逐字节相同),并打印了「克隆成功」。

在真实环境里怎么克隆

真实场景下,替换成本机设备即可:

# 把 /dev/sda 整块盘克隆到 /dev/sdb(目标盘容量 >= 源盘)
dd if=/dev/sda of=/dev/sdb bs=4M status=progress

# 把一块盘备份成一个"镜像文件"(后续可再写回任意同规格磁盘)
dd if=/dev/sda of=/backup/sda.img bs=4M status=progress

# 只备份某个分区
dd if=/dev/sda1 of=/backup/sda1.img bs=4M status=progress
⚠️ 危险:把 of= 指向设备,会直接覆盖那块盘上所有数据。克隆前务必用 lsblkfdisk -l 反复确认源盘与目标盘设备名,绝不可写反。写反 = 把空白盘覆盖到源盘上,数据瞬间全没。

压缩备份与恢复

块设备里通常有大量「空洞」或未用空间(比如刚才的 ext4 空盘,8MB 里绝大多数是零)。直接 dd 会产生和磁盘一样大的文件,浪费空间。配合 gzip,可以让备份体积小一个数量级:

# 1. 压缩备份:dd 读出字节 → 管道喂给 gzip → 写为 .img.gz
dd if=/root/disk_a.img bs=1M status=none | gzip -c > /root/disk_a.img.gz

# 2. 对比原镜像与压缩后的大小
ls -lh /root/disk_a.img /root/disk_a.img.gz

# 3. 解压恢复:gunzip 解压 → 管道喂给 dd → 写回新镜像
gunzip -c /root/disk_a.img.gz | dd of=/root/disk_restore.img bs=1M status=none

# 4. 校验恢复结果
cmp /root/disk_a.img /root/disk_restore.img && echo '恢复成功: 解压后与原镜像一致'

dd 压缩备份与解压恢复

截图里 8.0M 的镜像被压缩成 8.6K,压缩率惊人——因为 ext4 空盘基本都是零字节,gzip 能高效压缩。恢复后用 cmp 校验,确认解压后的镜像与原镜像逐字节一致。

真实迁移场景

把压缩 pipelining 组合起来,就是一台服务器整盘迁移的经典套路:

# A 机:把 /dev/vda 整盘压缩备份成镜像
ssh root@A "dd if=/dev/vda bs=4M status=progress | gzip -c" > vda.img.gz

# B 机:解压并写入新盘 /dev/vdb
gunzip -c vda.img.gz | ssh root@B "dd of=/dev/vdb bs=4M status=progress"

这样即使磁盘很大,只要数据稀疏,备份和传输都能大幅提速。

测速:读写速度基准

dd 也常被用来粗略测磁盘读写速度——因为它能触发大块连续 I/O。先看读取速度(常见写法是 of=/dev/null,把读出的数据直接丢弃):

# 读 1G 数据到 /dev/null,看读取带宽
dd if=/dev/vda of=/dev/null bs=1M count=1024

演示机上对 /dev/vda(云服务器系统盘)实测读取,输出:

1073741824 bytes (1.1 GB, 1.0 GiB) copied, 8.57755 s, 125 MB/s
说明:这里读的是真实磁盘,125 MB/s 是云盘实际读取带宽。注意若用 if=/dev/zero 这类内存伪设备测出来的数字会快到离谱(能到 19 GB/s 以上),那是内存速度、不是磁盘速度,别被误导。想测磁盘真实写入速度,可以加 oflag=dsync(跳过页缓存直接落盘),但会慢很多也更伤盘。dd 测速只能当参考,讲究的基准测试建议用 fio

进度查看与 status=progress

大磁盘复制可能耗时很久,默认 dd 只在结束时打印一行汇总,期间什么都看不到,容易让人以为卡死了。加 status=progress 能在复制过程中持续显示已复制字节数、耗时与速率

# 实时进度(会对真实设备很管用)
dd if=/dev/sda of=/backup/sda.img bs=4M status=progress

输出会在过程中反复刷新,形如:

268435456 bytes (268 MB, 256 MiB) copied, 0.311182 s, 863 MB/s
256+0 records in
256+0 records out

status=progress 适合大文件、磁盘克隆这类长任务;反过来,脚本里只想安静执行、不要进度噪声时,用 status=none 最干净(我们前面的演示几乎都加了它)。

结语与常见坑

dd 是运维工具箱里「最锋利也最危险」的一把刀。总结几条经验:

  1. 先确认设备名再动手lsblkfdisk -l 看清楚 if/of 各是谁。
  2. of= 指向设备 = 覆盖。克隆/写入前备份好目标盘上的残留数据。
  3. 块大小影响速度。经验值 bs=1M~4M 大多数场景够用;追求极限再用 bs=64M 做对照。
  4. status=progress 看进度,长任务别裸跑。
  5. 配合 gzip 压缩镜像,能省大量磁盘空间与传输带宽。

掌握了这些,无论是给服务器做整盘镜像、迁移系统,还是临时生成测试文件,dd 都能帮你游刃有余地完成。

参考资料

发表评论

暂无评论,快来抢沙发吧!