2016-07-20 14:50:16, In: Linux, Hack
The biggest problem with compressed full-disk backups in Linux is "all or nothing" philosophy. If you make an image by streaming dd's output to GZip, making a ".img.gz" file, you will end with file which needs decompression before any processing. Want to extract one file - decompress everything! And you need storage for it.
As a help, we can use SquashFS - a compressed file system used in embedded device systems. To start, let's boot the computer off you favourite distro not to run from disk under backup and mount the drive which will be backed up (in this example it's mounted in /mnt/custom).
Then let's fill the empty space up:
root@sysresccd /mnt/custom % dd if=/dev/zero of=/mnt/custom/rubbish.tmp bs=16384
According to your drive you can use smaller or larger block sizes (bs). When it finally ends, we will get a drive filled to the maximum. Remove the file we created:
root@sysresccd /mnt/custom % rm /mnt/custom/rubbish.tmp
This way, we've completely blanked a free space with zeros, so it will compress much better. Unmount the drive under backup:
root@sysresccd /mnt/ % umount /mnt/custom
Now, let's mount drive to which an image will be written, here /mnt/backup. Go to backup's destination directory and make another empty subdirectory:
root@sysresccd /backup/dell % mkdir tempdir
Now let's invoke making of SquashFS container which contains a single file supplied by dd:
root@sysresccd /backup/dell % mksquashfs tempdir squash.img -p 'backup.img f 444 root root dd if=/dev/sda bs=4M'
You should see a nice progress bar which doesn't indicate anything meaningful as data which is compressed is constantly supplied. By default, SquashFS operates on known amount of data in existing filesystem, here it is in stream mode. This way we can make a compressed drive image. As the last step, remove the empty folder:
root@sysresccd /backup/dell % rmdir tempdir
In this example we don't care about it. Theoretically it is possible to wipe the swap partition by dd'ing on it data from /dev/zero (if you do it, PLEASE do not zero-fill your main partition! Double check partition numbers!) and then making it swap partiion again by mkswap. For sake of simplicity (and size of my 1GB swap contrary to 120GB whole drive) I decided to compress my swap (/dev/sda2) as is without erasing.
SquashFS compresses directory structure into mountable image. The mode we've invoked SquashFS is working using a 'virtual file' which is a file defined by SquashFS' input parameters:
backup.img is the name
f - is type - normal, regular file, not a directory, pipe or device
444 - read only for everyone
root root - User and Group ID.
dd if=/dev/sda bs=4M - finally the command whose output will be written to the file.
Just mount the image first:
root@sysresccd /mnt % mount squash.img /mnt/gentoo
I have Debian, i used this directory because it is in System Rescue CD. Go to the directory /mnt/gentoo, and you have your backup.img file. You can dd it on a drive you want or mount by:
root@sysresccd /mnt/gentoo % losetup -f backup.img
root@sysresccd /mnt/gentoo % losetup -a
to see to which loop device (loopX) it is mounted, e.g.
/dev/loop0: :3 (/livemnt/boot/sysrcd.dat)
/dev/loop1: :284731 (/mnt/backup/dell/squash.img)
/dev/loop2: : (/mnt/gentoo/backup.img)
root@sysresccd /mnt/gentoo % partprobe /dev/loop2
(see that in the listing above, our img file inside SquashFS volume is mounted in loop2) and mount the partition you want:
root@sysresccd /mnt/gentoo % mount /dev/loop2p1 /mnt/custom
to get files you need from it. In some systems devices loopXpY are present in /dev/mapper/ directory. Try the partitions, as you will get swap and other partitions too.
Unmounting goes reverse way:
root@sysresccd /mnt %umount /mnt/custom
root@sysresccd /mnt losetup -d /dev/loopX
root@sysresccd /mnt umount /mnt/gentoo
Comparison has been made on Dell D430 (Intel Core 2 2x1.33GHz, 2GB RAM) with MX Nano 120GB SSD drive as backup source filled to ca. 75%, and USB 2TB Seagate Xpansion hard disk as destination. USB ports are 2.0.
- SquashFS: 4 hours
- img.gz: 3 hours 50 minutes
- SquashFS: 59.353.276.416 bytes
- img.gz: 59.327.461.230 bytes
Summing up, by the cost of a bit larger file and slightly longer time we get a possibility to mount the compressed image.