Clone whole partition or hard drive to a sparse file

I like to clone a whole partition or a whole hard drive onto a larger external disk but like to create a sparse file. I often use dd for cloning, but it doesn’t support sparse files. As a workaround I used something like:

cp --sparse=always <(dd if=/dev/sda1 bs=8M) /mount/external/backup/sda1.raw

However this is a little too tricky for my taste and doesn’t allow me to resume the process if aborted. It is funny that there is a NTFS tool for this (ntfsclone) but no such tool exists for the native file systems of Linux (EXT2-4).

Is there some better tool for this, e.g. a dd variant with sparse support?
I do not look for some proprietary software for disk backups but simply want to make a sparse clone copy which I can mount as loop device if required.

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You want dd_rescue.

dd_rescue -a -b 8M /dev/sda1 /mount/external/backup/sda1.raw

The copy may be interrupted at any time by Ctrl-C, showing the current position. This value can be used, when restarting by adding -s and the position to the original command, e.g.

dd_rescue -a -b 8M -s 42000k /dev/sda1 /mount/external/backup/sda1.raw

Even easier would be to specify a third file name, which acts as a log file. On restart dd_rescue will read that log file and pick up where it left off.

Method 2

Just for completeness the call for ddrescue. The --sparse or -S flag allows the destination to be written sparsely:

$ ddrescue -S -b8M /dev/sda1 /mount/external/backup/sda1.raw

Or with long option:

$ ddrescue --sparse --block-size 8M /dev/sda1 /mount/external/backup/sda1.raw

Or if you prefer MiBs:

$ ddrescue -S -b8Mi /dev/sda1 /mount/external/backup/sda1.raw

To allow the rescue to be interrupted and resumed, you can also make use of a logfile:

$ ddrescue -S -b8Mi /dev/sda1 /mount/external/backup/sda1.raw ~/sda1.rescue.log

Note that GNU ddrescue and dd_rescue are different programs. But GNU ddrescue seems to be more widespread. For example it is already packaged with GRML.

Method 3

There was a patch offered in 2007 to provide sparse file support in GNU dd, but it looks to have not made it into coreutils (at least not as of 8.4). I doubt dd has changed too much since then, the patch might apply against the current version without a lot of work.

I’m also really impressed by the creative use of cp in your question, and it got me on the track of using it to accomplish resuming (here resuming from ~80M into the source):

cp --sparse=always 
  <(dd if=/dev/sda1 bs=8M skip=10) /dev/stdout 
  | dd bs=8M seek=10 of=/mount/external/backup/sda1.raw

Edit: scratch that. The second dd would of course be seeking to the wrong position in the output file, since it’s not the same length as the input.

Method 4

Just adding my 2 cents. Another way to create a sparse file from a raw disk is with qemu-img using something like:

qemu-img convert -f raw /dev/sda /tmp/sda.raw

You can use this on a single partition as well. Also, you have the option to convert the raw disk/partition to any other format that qemu-img supports (QCOW2, VHD[x], vmdk, etc)

Method 5

Another option is rsync. For example:

rsync -SP --copy-devices /dev/sda1 /mount/external/backup/sda1.raw

Explanation:

  • -S/--sparse to skip sparse blocks on write
  • -P/--partial --progress to show progress and keep partially transferred files
  • --copy-devices to copy device contents1

You can add --append to resume an interrupted copy (or --append-verify to confirm the checksum over both new and old data matches).

Footnotes
  1. The --copy-devices option is provided by copy-devices.diff from rsync-patches, so it may not be present on some systems. It is included by Fedora, Ubuntu, Debian (until 3.2.0-1, see Bug 992215), and likely others.

Method 6

Note: this doesn’t work for the reasons described in the comments, I’m leaving it here for reference.

Monitor the statistics of dd by using kill -USR1:

$ cp --sparse=always <(dd if=/dev/urandom bs=8M) 
    /mount/external/backup/sda1.raw&
$ watch kill -USR1 `pidof -s /bin/dd`

Resume by using skip/seek:

$ i_bytes= # get from the last dd statistic
$ o_bytes=`du -b /mount/external/backup/sda1.raw | cut -f 1`   
$ cp --sparse=always <(dd if=/dev/urandom bs=8M skip=$i_bytes 
    seek=$o_bytes) /mount/external/backup/sda1.raw&
$ watch kill -USR1 `pidof -s /bin/dd`

Without $i_bytes it would be more difficult to resume. It’s probably easiest to log the dd statistics to a file in case the machine crashes or whatever.

Method 7

There are xfsdump and xfsrestore for XFS which has been a native Linux filesystem for quite a long time.

Method 8

Why not simply:

cp --sparse=always /dev/sda1 /mount/external/backup/sda1.raw

Method 9

It appears the OP is specifically looking to clone an EXT 2/3/4 filesystem. There is a tool to do just exactly this called e2image. And can be used like so:

e2image -rap <source> <dest>

This will create a sparse file on filesystems that support sparse files and will create a raw filesystem image, but there are other options for other formats (eg. QCOW2).

The problem with using dd or dd_rescue to sparsely copy filesystems is that they aren’t that smart. So if you have a filesystem that has been in use for a long time, its likely that you have many free blocks that are not zero-filled. These will get copied to the image file unnecessarily. So you could end up with an image the size of the filesystem even though df shows, say, 50% utilization. This can be worked around by using TRIM or zero-filling free blocks before using these commands. Or you could just use e2image and not worry about it.


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x