Linux磁盘克隆
2026-02-14
运维
00
请注意,本文编写于 49 天前,最后修改于 5 天前,其中某些信息可能已经过时。

目录

一、为什么需要物理级磁盘克隆?
1.1 场景对比:文件级备份 vs 块级克隆
二、方案一:图形界面 Live USB 本地克隆(推荐新手)
2.1 准备工具
2.2 启动进入 Live 环境
2.3 磁盘识别与保护
2.4 执行克隆(带进度显示)
2.5 完整性校验(关键步骤)
2.6 修复引导(跨硬件必需)
2.7 避免 UUID 冲突(克隆后必做)
三、方案二:Server 版 Live 无图形克隆(服务器场景)
3.1 进入 TTY 控制台
3.2 强制刷新磁盘列表
3.3 手动网络配置(如需联网下载工具)
四、方案三:网络对传克隆(无物理接触远程服务器)
4.1 场景与限制
4.2 直连网络配置
4.3 无加密高速传输(内网专用)
4.4 SSH 加密传输(跨公网/安全要求)
4.5 传输后校验
五、故障排查与进阶技巧
5.1 克隆后无法启动
5.2 处理坏道磁盘
5.3 压缩克隆(磁盘空间不足时)
5.4 并行克隆多盘
六、工具对比与选型建议
七、一键克隆脚本(Live 环境专用)

一、为什么需要物理级磁盘克隆?

1.1 场景对比:文件级备份 vs 块级克隆

场景文件级备份(rsync/tar)块级克隆(dd/pv)
系统迁移❌ 需重新安装引导✅ 完整复制包括引导扇区
加密磁盘❌ 无法读取加密内容✅ 逐扇区复制,加密状态保留
LVM/RAID❌ 需重建卷结构✅ 元数据一并复制
坏道恢复❌ 跳过损坏文件✅ 可配合 conv=noerror,sync 强制读取
取证分析❌ 修改时间戳✅ 比特级一致,哈希可验证

核心原则:操作系统、引导加载器、分区表、隐藏扇区(如UEFI启动分区)必须块级复制才能确保启动能力。


二、方案一:图形界面 Live USB 本地克隆(推荐新手)

2.1 准备工具

展开代码
所需物品: - Ubuntu Desktop ISO(≥20.04,带图形界面) - Rufus/Ventoy 制作的启动U盘(≥4GB) - 目标磁盘(容量≥源盘,接口兼容SATA/NVMe) - 可选:USB硬盘盒(用于笔记本外接)

2.2 启动进入 Live 环境

展开代码
开机 → BIOS/UEFI(按Del/F2/F12)→ 关闭 Secure Boot → 选择U盘启动 → 选择 "Try Ubuntu"(不要选Install)

关键:Live 环境的内核不挂载本地磁盘,确保源盘处于离线状态

2.3 磁盘识别与保护

展开代码
# 查看所有磁盘拓扑 lsblk -fp 典型输出: NAME FSTYPE LABEL UUID MOUNTPOINT /dev/sda ← 源盘(系统盘,正在运行) ├─/dev/sda1 vfat EFI 1234-5678 ├─/dev/sda2 ext4 rootfs a1b2c3d4-e5f6-7890-abcd-ef1234567890 └─/dev/sda3 swap 8765-4321-fedc-ba09-876543210987 /dev/sdb ← 目标盘(全新或待覆盖) /dev/sdc iso9660 Ubuntu 22.04 LTS amd64 ← 启动U盘

关键安全操作:设置只读锁

展开代码
# 对源盘设置内核级只读标记(防止任何误写) sudo blockdev --setro /dev/sda # 验证只读状态 sudo blockdev --getro /dev/sda # 输出 1 表示只读生效 # 如需临时解除(谨慎) # sudo blockdev --setrw /dev/sda

原理blockdev --setro 修改内核块设备标志,即使 root 用户也无法写入,比 mount -o ro 更底层可靠。

2.4 执行克隆(带进度显示)

展开代码
# 安装进度工具 pv(Pipe Viewer) sudo apt update sudo apt install -y pv # 方案A:精确进度(需知道源盘大小) sudo pv -tpreb -s $(blockdev --getsize64 /dev/sda) /dev/sda | \ sudo dd bs=4M of=/dev/sdb iflag=fullblock # 方案B:简单进度(无总进度条,仅速率) sudo pv /dev/sda | sudo dd bs=4M of=/dev/sdb # 参数说明: # -t: 时间统计 -p: 进度条 -r: 速率 -e: 剩余时间 -b: 已传输字节 # bs=4M: 4MB块大小,平衡内存与效率 # iflag=fullblock: 确保每次读取完整块

克隆时间估算

源盘类型容量典型速度耗时
SATA SSD500GB400 MB/s~21分钟
NVMe SSD1TB1 GB/s~17分钟
机械硬盘2TB150 MB/s~3.7小时

2.5 完整性校验(关键步骤)

展开代码
# 方法1:全盘 MD5(准确但极慢,大盘不推荐) sudo md5sum /dev/sda > /tmp/sda.md5 & sudo md5sum /dev/sdc > /tmp/sdc.md5 & wait diff /tmp/sda.md5 /tmp/sdc.md5 && echo "✅ 校验通过" || echo "❌ 数据不一致" # 方法2:抽样校验(推荐,平衡速度与可靠性) # 每 1MB 抽样前 4KB,覆盖全盘关键区域 sample() { local offset=$1 local device=$2 sudo dd if=/dev/$device bs=4K count=1 skip=$((offset/4)) 2>/dev/null | md5sum | cut -d' ' -f1 } echo "开始抽样校验(每1MB抽样4KB)..." total_mb=$(($(blockdev --getsize64 /dev/sda) / 1048576)) match=0 mismatch=0 for i in $(seq 0 1048576 $((total_mb * 1048576))); do if [ $((i/1048576)) -ne 0 ] && [ $(( (i/1048576) % 1000 )) -eq 0 ]; then echo "已检查 $((i/1048576)) / $total_mb MB..." fi hash_sda=$(sample $i sda) hash_sdb=$(sample $i sdb) if [ "$hash_sda" = "$hash_sdb" ]; then ((match++)) else ((mismatch++)) echo "⚠️ 差异发现于偏移 $i bytes" fi done echo "匹配: $match, 不匹配: $mismatch" [ $mismatch -eq 0 ] && echo "✅ 抽样校验通过" || echo "❌ 发现差异,建议重新克隆"

2.6 修复引导(跨硬件必需)

展开代码
# 挂载新盘根分区(根据实际分区调整) sudo mount /dev/sdb2 /mnt # 假设 sdb2 是 / 分区 # 绑定挂载虚拟文件系统(chroot 环境必需) for i in /dev /dev/pts /proc /sys /run; do sudo mount --bind $i /mnt$i done # 切换根环境 sudo chroot /mnt # 重新安装 GRUB(关键!适配新硬件) grub-install /dev/sdb # 写入 MBR/GPT 启动扇区 update-grub # 生成新配置,检测可用内核 # 处理 UEFI 启动(如适用) # grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu exit # 清理挂载 sudo umount -R /mnt

2.7 避免 UUID 冲突(克隆后必做)

展开代码
# 首次启动新盘前,在新盘环境中执行: sudo rm /etc/machine-id /var/lib/dbus/machine-id sudo systemd-machine-id-setup # 或克隆前在源盘执行(源盘会重新生成) # 注意:某些许可证绑定 machine-id,需提前记录

三、方案二:Server 版 Live 无图形克隆(服务器场景)

3.1 进入 TTY 控制台

展开代码
# 在 Ubuntu Server 安装界面选择语言后 Alt+F2 或 Ctrl+Alt+F2 # 进入 TTY2 # 如无法切换,尝试: Ctrl+Alt+F1 # 返回图形/主界面 Ctrl+Alt+F3 # 切换到 TTY3(备用)

3.2 强制刷新磁盘列表

展开代码
# 解决热插拔磁盘不识别问题 for host in /sys/class/scsi_host/host*; do echo "- - -" > "$host/scan" done sleep 2 # NVMe 磁盘特殊处理(PCIe 热插拔) echo 1 > /sys/bus/pci/rescan # 重新查看 lsblk -fp

3.3 手动网络配置(如需联网下载工具)

展开代码
# 识别网卡 ip link # 输出示例: # 1: lo: <LOOPBACK> ... # 2: ens33: <BROADCAST,MULTICAST> ... ← 物理网卡 # 启用网卡 sudo ip link set ens33 up # 配置静态IP(无DHCP环境) sudo ip addr add 192.168.1.99/24 dev ens33 sudo ip route add default via 192.168.1.1 echo "nameserver 8.8.8.8" | sudo tee /etc/resolv.conf # 测试 ping -c 3 8.8.8.8

替代方案:Alt+F1 返回安装界面,完成网络配置后 不继续安装,再 Alt+F2 返回 TTY,此时网络已配置好。


四、方案三:网络对传克隆(无物理接触远程服务器)

4.1 场景与限制

条件要求
带宽千兆以太网理论 125MB/s,万兆更佳
稳定性建议独立交换机或直连,避免生产网络
安全内网可信环境,或增加 SSH/SSL 隧道
时间1TB 数据 @ 100MB/s ≈ 2.8 小时

4.2 直连网络配置

展开代码
# 接收端(新机器,目标盘) sudo ip addr add 10.0.0.2/24 dev eth0 sudo ip link set eth0 up # 发送端(旧机器,源盘) sudo ip addr add 10.0.0.1/24 dev eth0 sudo ip link set eth0 up # 验证连通 ping -c 3 10.0.0.2 # 从发送端测试

4.3 无加密高速传输(内网专用)

接收端先启动监听

展开代码
sudo -i # 获取精确字节数用于进度显示 DISK_SIZE=$(blockdev --getsize64 /dev/sda) # 监听 12345 端口,接收后直接写入磁盘 nc -l 12345 | pv -s $DISK_SIZE | dd bs=4M of=/dev/sda iflag=fullblock # 参数说明: # nc -l: 监听模式 12345: 任意高端口 # pv -s: 设置总大小,显示真实进度百分比

发送端开始推送

展开代码
sudo -i DISK_SIZE=$(blockdev --getsize64 /dev/sda) # 读取源盘并通过 nc 发送 dd bs=4M if=/dev/sda iflag=direct | pv -s $DISK_SIZE | nc -q0 10.0.0.2 12345 # 参数说明: # iflag=direct: 绕过页缓存,减少内存压力 # nc -q0: 发送完立即关闭,不等待

4.4 SSH 加密传输(跨公网/安全要求)

展开代码
# 发送端(通过 SSH 隧道,自动加密) sudo dd bs=4M if=/dev/sda iflag=direct | \ pv -s $(blockdev --getsize64 /dev/sda) | \ ssh root@10.0.0.2 "dd bs=4M of=/dev/sda" # 或使用更高效的压缩+加密 sudo dd bs=4M if=/dev/sda | gzip -1 | \ pv | ssh root@10.0.0.2 "gunzip | dd bs=4M of=/dev/sda" # gzip -1: 最快压缩,减少带宽占用,CPU开销低

4.5 传输后校验

展开代码
# 快速校验:对比前 4GB 数据 cmp -n $((4*1024*1024*1024)) /dev/sda <(ssh 10.0.0.1 dd bs=4M count=1024 if=/dev/sda) # 或抽样校验(同2.5方法) # 在接收端执行抽样,与发送端对比

五、故障排查与进阶技巧

5.1 克隆后无法启动

现象原因解决
GRUB rescue> 提示引导扇区未写入或损坏chroot 重装 grub-install
UUID=xxx not foundfstab 使用旧 UUID编辑 /etc/fstab 更新 UUID,或使用 LABEL
内核 panic缺少新硬件驱动进入 Live 环境,chroot 后安装 linux-generic
黑屏无输出显卡驱动不匹配临时添加 nomodeset 启动参数

5.2 处理坏道磁盘

展开代码
# 源盘有坏道时,使用 conv 参数 sudo pv /dev/sda | sudo dd bs=4M of=/dev/sdb conv=noerror,sync # noerror: 读取错误继续 # sync: 错误位置填充空块,保持偏移对齐 # 事后标记坏块(ext4) sudo badblocks -v /dev/sdb > /tmp/badblocks.txt sudo e2fsck -l /tmp/badblocks.txt /dev/sdb2

5.3 压缩克隆(磁盘空间不足时)

展开代码
# 仅克隆已使用空间(需文件系统支持) sudo apt install partclone sudo partclone.ext4 -c -s /dev/sda2 | pv | gzip -c > /mnt/backup/sda2.img.gz # 恢复 gunzip -c sda2.img.gz | pv | sudo partclone.ext4 -r -o /dev/sdb2

5.4 并行克隆多盘

展开代码
# 同时克隆到多个目标(如 RAID1 预配置) sudo apt install tee sudo pv /dev/sda | sudo tee >(dd bs=4M of=/dev/sdb) >(dd bs=4M of=/dev/sdc) > /dev/null

六、工具对比与选型建议

工具适用场景优点缺点
dd通用块复制无处不在,精确控制无进度,出错即停
pv + dd本地克隆实时进度,可限速需计算总大小
partclone分区级备份只拷已用空间,快需匹配文件系统类型
Clonezilla批量部署图形界面,自动化需额外ISO,灵活性低
nc 网络对传远程无介质克隆无需中间存储无加密,需稳定网络
rsync文件级同步增量更新,可断点续传不复制引导扇区

七、一键克隆脚本(Live 环境专用)

展开代码
#!/bin/bash # clone_disk.sh - 安全磁盘克隆脚本 set -euo pipefail # 颜色输出 RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m'; NC='\033[0m' # 交互式选择磁盘 echo "可用磁盘:" lsblk -dpno NAME,SIZE,MODEL | grep -E "sd|nvme|hd" read -rp "源盘 (如 /dev/sda): " SRC read -rp "目标盘 (如 /dev/sdb): " DST # 确认 SRC_SIZE=$(blockdev --getsize64 "$SRC") DST_SIZE=$(blockdev --getsize64 "$DST") echo -e "${YELLOW}警告:目标盘 $DST 将被完全覆盖!${NC}" echo "源盘: $SRC ($(numfmt --to=iec-i $SRC_SIZE))" echo "目标: $DST ($(numfmt --to=iec-i $DST_SIZE))" if [ "$DST_SIZE" -lt "$SRC_SIZE" ]; then echo -e "${RED}错误:目标盘容量不足${NC}" exit 1 fi read -rp "确认继续? [yes/N]: " CONFIRM [ "$CONFIRM" != "yes" ] && exit 0 # 设置只读保护 echo "设置源盘只读保护..." sudo blockdev --setro "$SRC" # 执行克隆 echo "开始克隆..." sudo pv -tpreb -s "$SRC_SIZE" "$SRC" | sudo dd bs=4M of="$DST" iflag=fullblock # 校验 echo "抽样校验..." SAMPLES=1000 MATCH=0 for i in $(seq 0 $((SRC_SIZE/SAMPLES/1024/1024)) $((SRC_SIZE/1024/1024))); do OFFSET=$((i*1024*1024)) [ $OFFSET -ge $SRC_SIZE ] && break HASH_SRC=$(sudo dd if="$SRC" bs=4K count=1 skip=$((OFFSET/4/1024)) 2>/dev/null | md5sum | cut -d' ' -f1) HASH_DST=$(sudo dd if="$DST" bs=4K count=1 skip=$((OFFSET/4/1024)) 2>/dev/null | md5sum | cut -d' ' -f1) [ "$HASH_SRC" = "$HASH_DST" ] && ((MATCH++)) || echo "差异 at ${i}MB" done echo -e "${GREEN}校验通过: $MATCH/$SAMPLES 样本匹配${NC}" # 修复引导 echo "修复 GRUB 引导..." sudo mount "${DST}2" /mnt 2>/dev/null || sudo mount "${DST}1" /mnt for i in /dev /dev/pts /proc /sys /run; do sudo mount --bind $i /mnt$i; done sudo chroot /mnt grub-install "$DST" 2>/dev/null || echo "GRUB 安装失败,请手动处理" sudo umount -R /mnt echo -e "${GREEN}克隆完成!请执行 UUID 清理后重启${NC}" echo "sudo rm /etc/machine-id /var/lib/dbus/machine-id" echo "sudo systemd-machine-id-setup"

本文作者:zzz

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!