使用该fdisk -l
命令我得到以下答案:
Device Boot Start End Blocks Id System
/dev/sda1 * 2048 28266495 14132224 27 Hidden NTFS WinRE
/dev/sda2 28268544 28473343 102400 7 HPFS/NTFS/exFAT
/dev/sda3 28473344 132552703 52039680 7 HPFS/NTFS/exFAT
/dev/sda4 * 132556798 625141759 246292481 5 Extended
/dev/sda5 193996800 198092799 2048000 82 Linux swap / Solaris
/dev/sda6 234960896 625141759 195090432 7 HPFS/NTFS/exFAT
/dev/sda7 198094848 234950316 18427734+ 83 Linux
/dev/sda8 132556800 183756018 25599609+ 83 Linux
我想使用该dd
命令将磁盘的前三个分区复制到映像中。所以我安装了一个外部硬盘驱动器,进入其文件夹并输入:
# dd count=$((132552703-2048)) if=/dev/sda of=./newImage.image
但是这个命令将所有 sda 磁盘复制到我的外部硬盘驱动器,而不是仅仅复制到 sda3 分区末尾。
如何使用dd
创建一个从 sda1 开头开始并在 sda3 结尾结束的映像?
答案1
首先,方法如下:
首先做几乎就像你之前做的那样,但没有减法 - 并在计数上加一。
dd count=132552704 </dev/sda >img
接下来在一个进程中打印分区表
sed
,该进程可以筛选出您要删除的分区。sed
将向已打开您的d
第二个命令写入一个elete命令fdisk
img
sda4 及以上的每个分区的文件。fdisk -l img | sed -e'/sda4 /,$id' -e'g;$aw' | fdisk img
没有 3。你就完成了。
其次,原因如下:
部分成功...
我很确定你的命令几乎有效,但我敢打赌它比你想象的要好。
我希望当你这么说的时候复制所有 sda您认为是因为
fdisk -l
该映像的一个表明所有分区都包含在其中。不过,根据dd
您问题中的命令,provided/dev/sda
的扇区大小是相当标准的 512 字节(因此与dd
的默认块大小相同)那么您应该复制从/dev/sda
only 的字节 0 到除最后 2k 扇区之外的所有扇区/dev/sda3
。
关于部门...
您可以在下面看到
fdisk
输出报告单位。这就是每一个的大小部门报道fdisk
称。一个磁盘部门 可能为 4096 字节 - 如果它是最近制造的磁盘并处理高级格式扇区大小 - 否则很难找到未按标准逻辑 512 字节扇区大小分区的磁盘。就是这样
fdisk
的man
页面说:-u
,--units[=unit]
- 列出分区表时,显示大小部门或在气缸。默认显示尺寸为部门。为了向后兼容,可以使用该选项而不使用单元参数 - 那么使用默认值。请注意,可选的单位参数不能与
-u
选项由空格组成,正确的形式例如-u=cylinders
。
- 列出分区表时,显示大小部门或在气缸。默认显示尺寸为部门。为了向后兼容,可以使用该选项而不使用单元参数 - 那么使用默认值。请注意,可选的单位参数不能与
还有一些关于
dd
...dd
不能 默默地丢失数据。事实上,如果发生短读,dd
就是指定的成为非常对此发声:部分输入块是
read()
返回小于输入块大小的输入块。部分输出块是用比输出块大小指定的字节少的字节写入的输出块.........当有最后一个截断块,截断块的数量应写入标准错误...
"%u truncated %s\n"
,<number of truncated blocks>
,"record[s]"
阻止输入/输出...
- 但无论如何,那实际上不能发生在块设备 I/O 上。这就是块设备成为块设备的原因——有一个额外的层(有时是几个)对块设备(而不是字符设备)的缓冲保护。正是这种区别使得 POSIX 能够保证
lseek()
块设备上存在的文件 - 这是阻塞 I/O 的一个非常基本的原则。
- 但无论如何,那实际上不能发生在块设备 I/O 上。这就是块设备成为块设备的原因——有一个额外的层(有时是几个)对块设备(而不是字符设备)的缓冲保护。正是这种区别使得 POSIX 能够保证
总结...
- 所以你已经复制了全部您的设备直到您指定的点,但问题是,第一的2k 个扇区
/dev/sda
将包含其全部的分区表,因此您可以将所述分区表复制到您的映像中,因此fdisk -l
您的映像将报告全部的分区/dev/sda
,无论这些分区的数据是否实际驻留在该映像文件中。当然,cat
如果您愿意,您可以将单独的数据分区单独放入单独的映像文件中 - 但在这种情况下,您会完全丢失分区表。您真正要做的就是删除未复制的分区,并确保复制全部你所做的那些。
- 所以你已经复制了全部您的设备直到您指定的点,但问题是,第一的2k 个扇区
第三,我是这样知道的:
这将创建一个4G
./img
文件充满 NUL。</dev/zero >./img \ dd ibs=8k obs=8kx1b count=1kx1b
524288+0 records in 1024+0 records out 4294967296 bytes (4.3 GB) copied, 3.53287 s, 1.2 GB/s
这将分区
./img
将您的磁盘与前三个分区匹配,但比例为 1/16:(set "$((p=0))" 28266495 27 \ 28268544 28473343 2\\n7 \ 28473344 132552703 3\\n7 while [ "$#" -ge "$((p+=1))" ] do printf "n\np\n$p\n%.0d\n%d\nt\n%b\n" \ "$(($1/16))" "$(($2/16))" "$3" shift 3 done; echo w )| fdisk ./img >/dev/null
现在我们可以看看它。
fdisk -l ./img
Disk ./img: 4 GiB, 4294967296 bytes, 8388608 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0x5659b81c Device Boot Start End Sectors Size Id Type ./img1 2048 1766655 1764608 861.6M 27 Hidden NTFS WinRE ./img2 1766784 1779583 12800 6.3M 7 HPFS/NTFS/exFAT ./img3 1779584 8284543 6504960 3.1G 7 HPFS/NTFS/exFAT
我还将在三个分区上放置一些实际的文件系统和文件。
sudo sh -c ' trap "$1" 0 cd /tmp; mkdir -p mnt for p in "$(losetup --show -Pf "$0")p"* do mkfs.vfat "$p" mount "$p" mnt echo "my part# is ${p##*p}" \ >./mnt/"part${p##*p}" sync; umount mnt done' "$PWD/img" 'losetup -D'
这是所有结束位置的字节偏移量......
grep -Ebao '(my[^0-9]*|PART)[123]' <./img
2826272:PART1 2830336:my part# is 1 904606240:PART2 904624640:my part# is 2 917656608:PART3 917660672:my part# is 3
但是您是否注意到,fdisk
在我们使用文件系统格式化分区之前,它非常乐意报告分区的大小?这是因为分区表位于磁盘的最头部 - 它只是一个布局,仅此而已。不需要实际存在任何分区即可进行报告。它们仅在 的前 1M 内逻辑地映射出来./img
。手表:
让我们尝试只删除前两个分区
./img
......<./img >./img2 dd count=1779583
1779583+0 records in 1779583+0 records out 911146496 bytes (911 MB) copied, 1.84985 s, 493 MB/s
我们再来
grep
一次...grep -Ebao '(my[^0-9]*|PART)[123]' <./img2
2826272:PART1 2830336:my part# is 1 904606240:PART2 904624640:my part# is 2
并获取
fdisk
报告...fdisk -l ./img2
Disk ./img2: 869 MiB, 911146496 bytes, 1779583 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xcbcab4d8 Device Boot Start End Sectors Size Id Type ./img2p1 2048 1766655 1764608 861.6M 27 Hidden NTFS WinRE ./img2p2 1766784 1779583 12800 6.3M 7 HPFS/NTFS/exFAT ./img2p3 1779584 8284543 6504960 3.1G 7 HPFS/NTFS/exFAT
现在这很好奇。fdisk
似乎仍然相信有第三个分区扩展到磁盘的 4G,它也似乎相信大小只有 869M!
也许我们应该从分区表中删除第三个分区。
printf %s\\n d 3 w | fdisk ./img2 >/dev/null
现在让我们看看是否可以挂载我们复制的分区以及我们的文件是否保持不变......
sudo sh -c ' trap "$1" 0 cd /tmp; mkdir -p mnt for p in "$(losetup --show -Pf "$0")p"* do mount "$p" mnt grep . /dev/null ./mnt/* umount mnt done' "$PWD/img2" 'losetup -D'
./mnt/part1:my part# is 1 ./mnt/part2:my part# is 2
显然这并非不可能。
答案2
这是不可能的,因为 dd 只是直接 1 个输入到 1 个输出 - 恢复会受到损害,因为您将 3 个分区合并为一个,而这不是备份,而 dd 仅适用于相同的副本。
你的答案可能是:
dd if=/dev/sda1 of=~/hdadisk1.img;
dd if=/dev/sda2 of=~/hdadisk2.img
dd if=/dev/sda3 of=~/hdadisk3.img
(如果需要,可以在脚本中)最后,您可以使用 hdadisk{1,3,3}.img 创建映像,不过将这些映像保存在分区中进行备份是更好的做法。
答案3
dd count=$((132552703-2048))
从输入的开头复制 132552703-2048 个 512 字节的块。块大小为fdisk
1 kB = 1024 字节。所以你面临三个问题:
- 您指定的尺寸是您想要的尺寸的一半。
- 您没有表明您想以偏移量开始复制。
- 你的减法有一个栅栏错误:它错过了最后一个块——块的数量是(结束块偏移)-(起始块偏移)+ 1。
所以你可以用
dd bs=1k skip=2048 count=$((132552703-2048+1)) if=/dev/sda of=./newImage.image
我认为这会起作用——dd
可能会默默地丢失数据,但我认为块设备上的 1kB 块或 Linux 上的常规文件就可以了。但很慢。
复制单个分区的最直接方法就是直接复制它。
cat /dev/sda1 >sda1.image
cat /dev/sda2 >sda2.image
cat /dev/sda3 >sda3.image
最好将分区复制到单独的文件中,否则不在文件开头的分区将难以使用。如果您确实希望将三个分区放在同一个文件中,可以将它们连接起来:
cat /dev/sda1 /dev/sda2 /dev/sda3 >newImage.image
答案4
简单快速的答案是:
dd skip=2048 count=132552703 status=progress if=/dev/sda of=./newImage.image
默认情况下,fdisk -l 返回分区大小(以扇区为单位),每个扇区 512 字节
您可以确认在 fdisk 输出中应该显示如下内容:
Disk /dev/sda: 256 GiB, 274877906944 bytes, 536870912 sectors
Disk model: Virtual Disk
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
dd 还使用 512 字节作为开关“bs”、“cbs”、“ibs”和“obs”的默认值
bs=BYTES read and write up to BYTES bytes at a time (default: 512);
overrides ibs and obs
cbs=BYTES convert BYTES bytes at a time
conv=CONVS convert the file as per the comma separated symbol list
count=N copy only N input blocks
ibs=BYTES read up to BYTES bytes at a time (default: 512)
if=FILE read from FILE instead of stdin
iflag=FLAGS read as per the comma separated symbol list
obs=BYTES write BYTES bytes at a time (default: 512)
of=FILE write to FILE instead of stdout
oflag=FLAGS write as per the comma separated symbol list
seek=N skip N obs-sized blocks at start of output
skip=N skip N ibs-sized blocks at start of input
status=LEVEL The LEVEL of information to print to stderr;
'none' suppresses everything but error messages,
'noxfer' suppresses the final transfer statistics,
'progress' shows periodic transfer statistics
确认您可以使用 dd 本身创建一个块文件,如下所示:
dd if=/dev/urandom of=测试计数=1
文件大小应为 512 字节
因此,要创建一个分区或一组分区的映像,您所要做的就是从 fdisk 的输出中获取分区或第一个分区开头的扇区数,并将其用作 dd 参数“skip”的值",然后是分区末尾或最后一个分区的扇区数,并将其设置为 dd 参数“count”的值。
如果 fdisk 和 dd 之间存在块大小差异,您始终可以使用参数“bs”在 dd 中指定块大小,以确保 fdisk 输出与 dd 将使用的块大小匹配。