How to mount a compressed disk image?
If I make a disk image and compress it with gzip/xz/etc is there a way to mount it directly without first uncompressing it?
Say I've used
sudo dd if=/dev/sdc1 | gzip -9 > image1.dd.gz
how can I mount the original image, without creating an uncompressed copy first?
Or I've used
sudo dd if=/dev/sdc | gzip -9 > wholedisk.dd.gz
and the disk has multiple partitions, would that make it any harder?
With an uncompressed image of a whole disk then using kpartx
or newer versions of losetup
with it's -P
flag should create a loop for each partition.
But is there a way to mount/losetup/read the compressed image?
If it won't work for gzip/xz, is there any compression method this would work for?
Note on duplicate Q
The currently suggested duplicate
- Mount single partition from image of entire disk (device) , while being an excellent useful Q
DOES NOT USE COMPRESSION, and IS NOT A DUPLICATE.
mount
will not mount a compressed image by itself.
You can use squashfs
to compress disk images and then mount them.
Create the disk image
If you haven't got a disk image yet use dd
to create one:
dd if=/dev/sda1 of=/tmp/sda1.img bs=4M
Compress the image with squashfs
Install squashfs
:
apt-get install squashfs-tools
Compress the image:
mksquashfs /tmp/sda1.img /tmp/sda1.squash.img
Or Stream the compression (don't need a temporary dd file)
mkdir empty-dir
mksquashfs empty-dir squash.img -p 'sda_backup.img f 444 root root dd if=/dev/sda bs=4M'
Compliments to terminator14 at UbuntuForums.org. Definitions/Explanations:
-
empty-dir
- "source" dir. Basically in our case, just an empty dir to satisfy mksquashfs' input arg format -
squash.img
- the destination and filename of the output squashfs file -
sda_backup.img
- the name of the dd backup INSIDE the squashfs file -
f
- specifies that sda_backup.img is a regular file (as opposed to a directory, block device, or char device) -
444
- permissions of the sda_backup.img file inside the squashfs image -
root root
- UID and GID for the sda_backup.img file inside the squashfs image. Can be specified by decimal numbers, or by name -
dd if=/dev/sda bs=4M
- the dd command used to read the device we want backed up
Mount the image
First mount the squashfs
image:
mkdir /mnt/squash
mount /tmp/sda1.squash.img /mnt/squash
This will present the un-compressed disk image for you to mount:
mkdir /mnt/sda1
mount /mnt/squash/sda1.img /mnt/sda1
Or if it's a full drive image (partitioned) you could use losetup
to attach the dd image to a loop device (possibly optional) and then kpartx -a
or partprobe
to find & separate the partitions to separate devices, or even vgscan
/ vgchange -ay
if there's LVM.
I was able to get an NBD server to "serve up" an un-compressed version of a .gz or .xz file. I'm not sure if it has to read the entire compressed file very often (only tested so far with small files in ram) but at least it works without having to extract a whole un-compressed copy.
Viewing a gz / xz Compressed dd image "on-the-fly"
-
Install nbdkit & client
apt install nbdkit nbd-client
-
Create demo "dd" style file - an empty 50M file with an ext filesystem & zip it (Optional for testing only)
fallocate -l 50M 50m mkfs.ext3 -v 50m
Then compress with either gzip or xz
gzip -vk9 50m xz -v9k 50m
Note: An
xz
option of--block-size=16MiB
should give better random access performance, but at the expense of less compression (maybe 1%?). See the nbdkit's xz plugin description. -
Run server on COMPRESSED image
nbdkit -v --no-fork -i 127.0.0.1 /usr/lib/i386-linux-gnu/nbdkit/plugins/nbdkit-gzip-plugin.so file=~/Downloads/50m.gz
or for xz
nbdkit -v --no-fork -i 127.0.0.1 /usr/lib/i386-linux-gnu/nbdkit/plugins/nbdkit-xz-plugin.so file=~/Downloads/50m.xz
The
--no-fork
tells the server "Don't fork into the background" so seeing possible error messages & killing it with CTRL-C is a little easier.-v
may / will show too many status messages, especially when reading. -
Run client (in another terminal/window)
sudo nbd-client -nofork 127.0.0.1 10809 /dev/nbd0
The
-nofork
is similar to-no-fork
above, but I could not kill the client with CTRL-C,kill <pid>
, orsudo kill <pid>
. Ending the server with CTRL-C stopped both server & client. -
Observe that
/dev/nbd0
is now identical to UN-COMPRESSED image$ sudo diff -s /dev/nbd0 ~/Downloads/50m Files /dev/nbd0 and /home/user/Downloads/50m are identical
/dev/nbd0
can now be used just like the uncompressed image; mounted, read/copy withdd
, or usekpartx
,partprobe
,vgscan
/vgchange
, etc!
Thanks to Cristian Ciupitu on Unix & Linux, though it took a little more digging to find the plugin & get everything going together.