这个命令是干啥的
dd 的全称是 "data duplicator"。数据复制器。这名字听着很普通,但它能干的事情一点都不普通。
简单说,dd 就是在字节层面上复制数据。不像 cp 是按文件复制,dd 直接操作磁盘块,连文件系统都不用管。这意味着你可以:
- 把一个整块硬盘克隆到另一个硬盘
- 创建一个指定大小的空文件
- 测试磁盘读写速度
- 从损坏的磁盘里抢救数据
我第一次被 dd 震到是有次要快速创建一个 1GB 的交换文件。用 fallocate 当时不太熟,就用 dd 几秒钟搞定了。后来发现做磁盘对拷、做 U 盘启动盘都用得上。
dd 的语法风格在 Linux 命令里比较独特,参数用的是 选项=值 的格式:
dd if=输入文件 of=输出文件 bs=块大小 count=块数量 status=progress
- ·
if=:input file,数据来源 - ·
of=:output file,输出到哪 - ·
bs=:block size,每次读写多少字节 - ·
count=:读写多少个块
基本用法(3分钟上手)
创建指定大小的文件
# 创建一个 100MB 的空文件,内容全是 0
dd if=/dev/zero of=testfile bs=1M count=100
# 查看创建结果
ls -lh testfile
# 输出:-rw-r--r-- 1 root root 100M Mar 15 10:00 testfile
/dev/zero 是一个特殊的设备文件,读它会源源不断地输出 \0 字节(全是 0)。配合 bs 和 count 就能精确控制文件大小。
磁盘读写测速
# 测试磁盘写速度
dd if=/dev/zero of=/tmp/test bs=1M count=1000 conv=fdatasync
conv=fdatasync 确保数据真正写到磁盘上再出结果。不加这个参数,dd 报告的速度可能只是内存写入速度,比实际快很多。
# 测试磁盘读速度
dd if=/tmp/test of=/dev/null bs=1M count=1000
/dev/null 是黑洞设备,读出来的数据直接扔掉,纯粹测试读取性能。
制作 U 盘启动盘
# 把 ISO 镜像写入 U 盘(假设 U 盘是 /dev/sdb)
dd if=ubuntu-22.04.iso of=/dev/sdb bs=4M status=progress
一定要注意:of 指定的是磁盘设备(如 /dev/sdb),不是分区(如 /dev/sdb1)。写错了会把你系统盘干掉。我亲眼见过同事把 sdb 写成 sda,系统当场崩了。
显示进度
dd 默认是个闷葫芦,啥进度也不显示。大数据量的时候你会怀疑它是不是卡死了。
# status=progress 显示实时进度
dd if=/dev/sda of=/dev/sdb bs=4M status=progress
在较新的 Linux 上,status=progress 会显示当前速度、已传输数据量和剩余时间。
进阶骚操作
备份整个磁盘(磁盘对拷)
# 把 /dev/sda 完整克隆到 /dev/sdb(两台同型号同容量硬盘)
dd if=/dev/sda of=/dev/sdb bs=4M status=progress
这等于对拷整块盘,包括分区表、MBR、所有文件。插上 sdb 就能直接启动,跟 sda 一模一样。
但有个坑:sdb 的容量必须大于等于 sda。sdb 大一点没关系,小了就 GG。
创建交换文件
Linux 系统如果想增加交换空间,可以用 dd 创建交换文件:
# 创建 2GB 的交换文件
dd if=/dev/zero of=/swapfile bs=1M count=2048
# 设置正确权限
chmod 600 /swapfile
# 格式化成交换空间
mkswap /swapfile
# 启用交换文件
swapon /swapfile
查看效果:
# 查看交换空间状态
free -h
swapon --show
想让重启后自动生效,还要加一行到 /etc/fstab:
# 向 /etc/fstab 追加配置
echo '/swapfile none swap sw 0 0' >> /etc/fstab
磁盘性能基准测试
做运维的经常要评估新服务器的磁盘性能:
# 顺序写测试
dd if=/dev/zero of=/tmp/bench bs=1M count=2048 conv=fdatasync 2>&1
# 顺序读测试
dd if=/tmp/bench of=/dev/null bs=1M count=2048 2>&1
# 小文件块性能测试(4K 块大小,模拟小文件场景)
dd if=/dev/zero of=/tmp/bench4k bs=4K count=256000 conv=fdatasync 2>&1
块大小不同,测出来的速度差很多。大块(1M)测的是顺序吞吐,小块(4K)测的是 IOPS 能力。
用 dd 填充随机数据
# 用 /dev/urandom 创建随机内容的文件
dd if=/dev/urandom of=randomfile bs=1M count=10
这常用于测试、加密场景,或者把数据填成随机值再删除(安全擦除的粗糙版)。
# 安全擦除分区(写满随机数据,恢复难度极高)
dd if=/dev/urandom of=/dev/sdb1 bs=4M status=progress
dd 配合 gzip 做压缩备份
硬盘对拷时会复制空间和数据。可以用管道压缩节省空间:
# 把磁盘压缩成镜像文件
dd if=/dev/sda bs=4M | gzip > disk_backup.img.gz
# 恢复
gunzip -c disk_backup.img.gz | dd of=/dev/sda bs=4M
我有个 16GB 的 U 盘,实际数据只有 3GB 左右,压缩后镜像文件才 1.2GB。
dd 和数据恢复
# 跳过坏块(conv=noerror 遇到错误继续,sync 用 0 填充)
dd if=/dev/sda of=/dev/sdb bs=4K conv=noerror,sync status=progress
不加 conv=noerror,dd 读到坏块就停了,数据救不回来。
避坑指南
1. 永远确认 of= 的目标
dd 不问你"确认吗"。你说 of=/dev/sda,它直接给你抹盘。
# 写之前用 lsblk 确认设备名
lsblk
我建议你把这条命令记在脑子里,每次用 dd 写磁盘之前先跑一遍。
2. dd vs cp 对大文件的区别
| 场景 | dd | cp |
|---|
| 复制普通文件 | 都可以,cp 更自然 | 推荐 |
| 克隆整块磁盘 | dd 是唯一选择 | 不行 |
| 创建特定大小的文件 | dd if=/dev/zero bs=1M count=100 | fallocate 更快 |
| 跨设备复制大文件 | 两者差不多 | 更直观 |
| 跳过坏块复制 | dd conv=noerror | 不行 |
对于普通文件的复制,cp 更安全也更直观。dd 的优势在操作设备和块级别的场景。
3. bs 大小影响性能
# bs 太小,大量 I/O 操作,慢
dd if=/dev/sda of=/dev/sdb bs=512
# bs 合适,平衡性能和内存
dd if=/dev/sda of=/dev/sdb bs=4M
4M 是大多数场景下的好选择。bs 设太大(比如 1G)也不会更快,反而占用内存。
4. 为什么 dd 卡住了那么久也不动
dd 默认静默执行,没有进度提示。大于 1GB 的操作建议都加上 status=progress。
想查看 dd 进度但不支持 status 参数的旧系统:
# 在另一个终端向 dd 进程发 USR1 信号,输出当前进度
kill -USR1 $(pgrep ^dd)
或者在执行前按 Ctrl+T(某些终端支持)。
5. 不要用 dd 创建有文件系统的文件
# 这是我用 dd 创建的空文件
dd if=/dev/zero of=document.txt bs=1K count=1
# 然后发现编辑器打开全是乱码
cat document.txt
因为 /dev/zero 输出的是空字节(\0),不是 ASCII 的空格。想创建空文本文件,用 touch 或者 echo "" > file。
实战场景(重点!结合真实运维场景)
场景一:云服务器创建交换文件
云服务器内存不够用,临时加交换空间:
# 检查当前内存和交换
free -h
# 当前内存是 2GB,想加 2GB 交换
dd if=/dev/zero of=/swapfile bs=1M count=2048 status=progress
# 设置权限(安全要求)
chmod 600 /swapfile
# 格式化
mkswap /swapfile
# 启用
swapon /swapfile
# 验证
free -h
我测试过,腾讯云 2C4G 的轻量服务器跑 Node 应用,内存吃紧的时候加上 2GB 交换,虽然慢了点,但至少不会 OOM 被杀。
场景二:给旧硬盘做安全销毁
离职交接或者淘汰服务器之前:
# 把整个磁盘写三遍随机数据
dd if=/dev/urandom of=/dev/sdb bs=4M status=progress
dd if=/dev/urandom of=/dev/sdb bs=4M status=progress
dd if=/dev/urandom of=/dev/sdb bs=4M status=progress
三遍随机覆盖之后,用专业恢复工具也基本读不出原始数据了。当然,这做法比较费时间,250GB 机械硬盘写一遍大概要几个小时。
场景三:制作树莓派系统卡
# 先把镜像解压
unzip raspbian-lite.zip
# 查看 SD 卡设备名
lsblk
# 写入(假设 SD 卡是 /dev/sdc)
sudo dd if=raspbian-lite.img of=/dev/sdc bs=4M status=progress
# 同步缓存
sync
写完之后 sync 一下确保数据都落盘了,拔卡不会丢数据。
场景四:替换服务器硬盘
服务器一块硬盘有坏道,急买一块新的,要对拷系统:
# 新硬盘插上后 lsblk 确认设备名
lsblk
# 旧盘 /dev/sda,新盘 /dev/sdb,大小相同
# 用 noerror,sync 跳过坏块
dd if=/dev/sda of=/dev/sdb bs=4M status=progress conv=noerror,sync
# 完成后检查新盘分区
fdisk -l /dev/sdb
# 启动后能挂在同一个设备用
注意:如果两块硬盘型号不同、容量不同,用 dd 对拷可能出问题。这时候用 dd + 分区工具 + rsync 组合更好。
今日作业(一道小题目)
题目:你接手一台服务器,内存 4GB 但没有配置交换空间,而且经常 OOM(内存耗尽)被杀进程。
要求:
1. 用 dd 创建一个 4GB 的交换文件(位置:/swapfile)
2. 设置正确的文件权限
3. 格式化为交换空间
4. 启用它,并确保重启后自动生效
5. 验证是否生效
写全你的命令序列。不限速。