dd在整个磁盘上,但不希望有空的部分


33

我有一个磁盘,例如/ 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

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

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


2
除@sudoer以外,以下所有答案都是错误的。正确的答案是使用dd conv=sparse
bahamat 2015年

@bahamat,不,gzip更好,因为它将压缩数据。
psusi 2015年

1
那和稀疏是不一样的。
bahamat 2015年

@bahamat,问题并非专门针对sprase;只是如何使图像占用更少的空间。
psusi 2015年

Answers:


37

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

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

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

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

如果您实际需要写入磁盘,可能伸缩性不是很好,并且可能会引起问题,但是,嘿。

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

注意:对固态硬盘可能有害,用户应在提交前考虑此操作。


如果我通过gzip运行它,是否需要在使用它之前解压缩它?通过gzip运行它,是否可以在dd进程中通过管道传输它?
乔纳森·汉森

3
是。 dd if=sda2.gz | gunzip > /dev/sda2dd if=/dev/sda2 | gzip > sda2.gz
Rob Bos 2012年

3
“您刚刚将零写入了设备上的所有可用空间”。我想,您的意思是分区,而不是设备。因此,您需要使用of每个分区的路径运行该命令。
jiggunjer'2

如果物理介质是SSD,则现在可能认为设备上的每个扇区都已使用。这将使SSD可以使用的备用扇区更少,从而可能会降低性能。如果驱动程序和固件具有TRIM支持,则该条件仅在您再次删除文件之前适用。如果在创建映像时将文件保留在适当的位置,则在还原映像后必须再次删除该文件。如果将映像还原到SSD,这可能会很有用。
kasperd '16

还有其他一些注意事项。由于此方法要求文件系统以读写方式安装,因此存在在复制过程中更改基础文件系统的风险,从而导致映像不一致。有一次我看到生成的副本非常不一致,以至于fsck在尝试修复副本上的不一致时实际上会出现段错误。填充设备也会导致其他需要写入媒体的进程失败。
kasperd '16

17

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

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

  2. 使用zerofill或just: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

PS:您应注意,在基于闪存的存储介质(即您的源文件系统为SSD)上,这不是一个好主意。


5
这是正确的答案。使用dd conv=sparse
bahamat 2015年

1
在闪存上执行此操作有什么问题?

2
@Dan(取决于硬件和软件的设计和配置)可能会导致对SSD的大量写入并缩短其使用寿命。总体而言,可以将数据从旧磁盘移动到新磁盘(或OP想要执行的操作),但是磁盘/分区级别的备份对于常规备份和还原(即使在HDD上)也不是一个好的解决方案。文件级备份(即,将文件从一个文件系统复制到另一文件系统)或文件系统级备份(使用BTRFS等文件系统btrfs snapshotbtrfs send工具)是IMHO的更好解决方案。
Sudoer

提示:如果你没有gz对你PATH(像我一样不上的GParted Live)的,您可以使用gzip -c来代替。
XtraSimplicity

11

将dd与count选项一起使用。

在您的情况下,您使用的是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

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

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

    sudo dd if=/dev/sda of=/your_directory/image_name.iso bs=8225280 count=526

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


FYI:显示单位气瓶,使用fdisk -l -u=cylinders /dev/sda
xinthose

3
为什么这不是公认的答案?它似乎是最少侵入性的选项,因为它不会修改源。
user33326

@ user33326,因为此答案非常适合不复制驱动器上的未分区空间,而不是分区中未使用的空间,这是OP关心的。
GDorn

8

尽管可以/dev/zero释放磁盘空间并可以使用dd conv=sparse/ gz -c,但在具有100 GB GB的空空间的巨大磁盘上,/dev/zeroing的速度很慢-更不用说其他答案指出的了,/dev/zero将SDD 写入EOF。

这是我遇到这种情况时所做的事情:

  • 在lubuntu实时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)。


1
这是真正的答案,只需使用count参数
Gordy

7

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

另一方面,空白空间将非常非常好地进行压缩,因此,如果您只关心存储空间,而不是例如写入时间,则只需将其通过gzip传递即可。


7
假设以前没有使用过可用空间。您可以先将可用空间归零,以确保压缩工作正常。
Sirex 2012年

1
真正。而且它只会使过程复杂化,并使过程花费更长的时间。
c2h5oh 2012年

6

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

如果您使用诸如partimageclonezilla或其他一些Linux克隆工具之类的工具,它们将为您自动处理大部分此类工作。


partimage和Clonezilla的实际上是足够聪明跳过阅读的自由空间,而不是依赖于你写零到它,然后有DD或gzip的下降或在阅读这些条款后压缩0。
psusi

2

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

定义磁盘的最后使用块:

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

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

dd if=/dev/sdX bs=512 count=$ct | gzip > BACKUP_FOLDER/sdX_$(date +"%Y-%m-%d").img.gz >>"$LOG"
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.