dd 在整个磁盘上,但不想要空白部分

Jon*_*son 45 linux hard-drive dd

我有一个磁盘,比如 /dev/sda。

这是 fdisk -l:

 Disk /dev/sda: 64.0 GB, 64023257088 bytes
255 heads, 63 sectors/track, 7783 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0000e4b5

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1   *           1          27      209920   83  Linux
Partition 1 does not end on cylinder boundary.
/dev/sda2              27         525     4000768    5  Extended
Partition 2 does not end on cylinder boundary.
/dev/sda5              27         353     2621440   83  Linux
/dev/sda6             353         405      416768   83  Linux
/dev/sda7             405         490      675840   83  Linux
/dev/sda8             490         525      282624   83  Linux
Run Code Online (Sandbox Code Playgroud)

我需要制作一个图像以存储在我们的文件服务器上,以用于刷新我们正在制造的其他设备,所以我只想要已用空间(仅约 4GB)。我想保留 mbr 等...因为该设备应该在复制完成后立即启动。

有任何想法吗?我以前一直在使用dd if=/dev/sda of=[//fileserver/file],但当时,我的主副本在 4GB 闪存上。

Rob*_*Bos 43

回到那天,我在嵌入式 Linux 发行版中遇到了类似的问题 - 在压缩图像之前清除所有垃圾。

dd if=/dev/zero of=asdf.txt. 等到它死了。删除 asdf.txt。

您刚刚将零写入设备上的所有可用空间。

现在获取磁盘映像并通过 gzip 运行它。瞧,稀疏的图像。

如果您确实需要写入磁盘,可能无法很好地扩展并且可能会导致问题,但是嘿。

您可以将磁盘的 rsync 快照复制到另一个卷,将其归零,然后获取该磁盘映像。

注意:可能对 SSD 有危害,用户在提交前应考虑此操作。

  • “您刚刚将零写入设备上的所有可用空间”。你的意思是分区,而不是设备,我想。因此,您需要使用每个分区的 `of` 路径运行该命令。 (5认同)
  • 是的。`dd if=sda2.gz | gunzip > /dev/sda2` 和 `dd if=/dev/sda2 | gzip > sda2.gz` (3认同)

Mic*_* TM 26

假设您要保存/dev/sdXN/tgtfs/image.raw并且您是 root:

  1. mkdir /srcfs && mount /dev/sdXN /srcfs

  2. 使用zerofill或只是:
    dd if=/dev/zero of=/srcfs/tmpzero.txt
    用零填充未使用的块;等待它完全填满文件系统然后:
    rm /srcfs/tmpzero.txt

  3. 使用 dd 获取图像并使用 conv=sparse 即时打零:
    dd conv=sparse if=/dev/sdxn of=/tgtfs/image.raw

如果你想使用压缩,你不需要用 dd 打零,因为零块是高度可压缩的:

dd if=/dev/sdxn | gz -c | dd of=/tgtfs/image.raw
Run Code Online (Sandbox Code Playgroud)

PS:您应该注意,定期在基于闪存的存储介质(即您的源文件系统为 SSD)上(用零填充文件系统)不是一个好主意,因为它会导致大量写入到您的 SSD 并缩短其使用寿命。(但偶尔传输数据也没关系)

  • 这是正确答案。使用`dd conv=sparse`。 (6认同)
  • @Dan(取决于硬件和软件设计和配置)它可能会导致对您的 SSD 进行大量写入并缩短其使用寿命。总的来说,将数据从旧磁盘移动到新磁盘(或 OP 想要做的)是可以的,但磁盘/分区级备份不是常规备份和恢复的好解决方案,即使在 HDD 上也是如此。文件级备份(即将文件从一个文件系统复制到另一个文件系统),或文件系统级备份(使用像 BTRFS 这样的文件系统,带有 `btrfs 快照` 和 `btrfs send` 工具)是更好的解决方案恕我直言。 (2认同)
  • 提示:如果您的“PATH”上没有“gz”(就像我在 GParted Live 上没有的那样),您可以使用“gzip -c”代替。 (2认同)

Tom*_*oby 17

使用带有计数选项的 dd。

在您的情况下,您使用的是 fdisk,所以我将采用这种方法。你的“sudo fdisk -l”产生了:

    Disk /dev/sda: 64.0 GB, 64023257088 bytes
    255 heads, 63 sectors/track, 7783 cylinders
    Units = cylinders of 16065 * 512 = 8225280 bytes
    Sector size (logical/physical): 512 bytes / 512 bytes
    I/O size (minimum/optimal): 512 bytes / 512 bytes
    Disk identifier: 0x0000e4b5

    Device Boot      Start         End      Blocks   Id  System
    /dev/sda1   *           1          27      209920   83  Linux
    Partition 1 does not end on cylinder boundary.
    /dev/sda2              27         525     4000768    5  Extended
    Partition 2 does not end on cylinder boundary.
    /dev/sda5              27         353     2621440   83  Linux
    /dev/sda6             353         405      416768   83  Linux
    /dev/sda7             405         490      675840   83  Linux
    /dev/sda8             490         525      282624   83  Linux
Run Code Online (Sandbox Code Playgroud)

您应该注意的两件事是 1) 单位大小,以及 2)“结束”列。在您的情况下,您的圆柱体等于 8225280 字节。在“结束”列中,sda8 终止于 525(即 525[units]*16065*512 = ~4.3GB)

dd 可以做很多事情,比如在一个偏移之后开始,或者在特定数量的块之后停止。我们将使用 dd 中的 count 选项来完成后者。该命令将如下所示:

    sudo dd if=/dev/sda of=/your_directory/image_name.iso bs=8225280 count=526
Run Code Online (Sandbox Code Playgroud)

其中 -bs 是块大小(最容易使用 fdisk 使用的单位,但只要在这些单位中声明了 count 选项,任何单位都可以这样做),而 count 是我们要复制的单位数(注意我们将计数增加 1 以捕获最后一个块)。

  • 为什么这不是公认的答案?这似乎是侵入性最小的选项,因为它不会修改源。 (6认同)
  • @ user33326 因为这个答案适合不复制驱动器上未分区的空间,而不是分区内未使用的空间,这是 OP 关心的。 (4认同)

Ash*_*pra 13

虽然/dev/zeroing 可用磁盘空间和使用dd conv=sparse/gz -c是可能的,但在空白空间以 100 s GB 运行的巨大磁盘上,/dev/zeroing 非常缓慢 - 更不用说其他答案指出的那样,/dev/zero在 EOF 之前使用 SDD。

当我遇到这种情况时,我是这样做的:

  • 在 lubuntu live CD 上,用于gparted将磁盘“缩小”到最小可能的大小,使其余空间未分配

  • 用于
    dd bs=1M count=<size_in_MBs> if=/dev/sdX | gzip -c --fast| dd of=/path/to/image.gz 创建快速压缩的图像(不用说,如果您有足够的空间来存储原始数据(或者倾向于减少 CPU 负载),您可能希望跳过压缩

  • 用于
    dd if=/path/to/image.gz | gunzip -c | dd bs=1M of=/dev/sdY 将数据复制回不同的磁盘
  • 用于gparted再次“扩大”分区

我还没有为多个分区尝试过,但我相信如果首先创建目标磁盘上的分区表并且仅通过dd读取/写入偏移量复制分区中包含的数据,则上述过程可以适用于复制“分区” (skip/seek选项dd,分别) 将是适当的要求。


c2h*_*5oh 9

你不能。dd是一个非常低级的工具,它无法区分文件和空白空间。

另一方面,空白空间会压缩得非常非常好,所以如果您只关心存储空间,而不是例如写入时间,那么只需通过 gzip 管道它。

  • 假设之前没有使用过可用空间。您可以先将可用空间归零以确保压缩按预期工作。 (8认同)
  • 真的。而且它只会使过程复杂化并使其花费更长的时间。 (3认同)

Zor*_*che 7

假设驱动器的其余部分是空的(全为零),您可以通过 gzip 管道传输 DD,这应该可以很好地压缩空白空间。您可以使用zerofree 之类的工具来确保您的空白空间实际上是空白的,因此它可以很好地压缩。

如果您使用诸如partimageclonezilla或其他一些 linux 克隆工具之类的工具,它们会自动为您处理大部分内容。


小智 5

接受的答案是不正确的。我同意上面的评论。我使用带有count参数的dd来定期备份我的磁盘。只需将设备的 BACKUP_FOLDER 和字母替换为“X”:

定义磁盘最后使用的块:

ct=$(fdisk -l | awk '$1 == "/dev/sdX" { print $3 }')
Run Code Online (Sandbox Code Playgroud)

然后克隆磁盘(不包括它的空白空间):

dd if=/dev/sdX bs=512 count=$ct | gzip > BACKUP_FOLDER/sdX_$(date +"%Y-%m-%d").img.gz >>"$LOG"
Run Code Online (Sandbox Code Playgroud)