如何修改image文件

时间:2022-10-20 08:56:38

方法一:mount成为一个loop device

参考http://smilejay.com/2012/08/mount-an-image-file/

方法一:找出分区开始的开始位置,使用mount命令的offset参数偏移掉前面不需要的,即可得到真正的分区。其具体步骤如下:
1. 用“fdisk -lu my.img”查询image信息;
2. 计算image内分区开始的地方(计算offset),用从N号sector(扇区)开始,则offset=N*M (M为一个sector的大小,一般为512)
3. 使用mount命令挂载为loop设备即可。 (如LVM分区,则会较复杂,请见本文最后的介绍)

[root@jay-linux image]# fdisk -lu rhel6u2.img
You must set cylinders.
You can do this from the extra functions menu.
 
Disk rhel6u2.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00048b34
 
      Device Boot      Start         End      Blocks   Id  System
rhel6u2.img1   *        2048     1026047      512000   83  Linux
Partition 1 does not end on cylinder boundary.
rhel6u2.img2         1026048   104857599    51915776   8e  Linux LVM
Partition 2 has different physical/logical endings:
     phys=(1023, 254, 63) logical=(6527, 21, 22)
[root@jay-linux image]# echo $((2048*512))
1048576
[root@jay-linux image]# mount -o loop,offset=1048576 rhel6u2.img /media/
[root@jay-linux image]# cd /media/
[root@jay-linux media]# ls
config-2.6.32-220.el6.x86_64         initramfs-3.5.0.img               System.map-2.6.32-279.el6.x86_64
config-2.6.32-279.el6.x86_64         lost+found                        System.map-3.5.0
efi                                  symvers-2.6.32-220.el6.x86_64.gz  vmlinuz
grub                                 symvers-2.6.32-279.el6.x86_64.gz  vmlinuz-2.6.32-220.el6.x86_64
initramfs-2.6.32-220.el6.x86_64.img  System.map                        vmlinuz-2.6.32-279.el6.x86_64
initramfs-2.6.32-279.el6.x86_64.img  System.map-2.6.32-220.el6.x86_64  vmlinuz-3.5.0
[root@jay-linux media]# echo $((1026048*512))
525336576
[root@jay-linux media]# umount /media
[root@jay-linux media]# cd /home/image/
[root@jay-linux image]# umount /media
[root@jay-linux image]# mount -o loop,offset=525336576 rhel6u2.img /media/
mount: unknown filesystem type 'LVM2_member'
(镜像文件中的LVM分区mount的问题,本文最后单独说明)
 
 
[root@jay-linux image]# fdisk -lu sles11sp2-i386.img
You must set cylinders.
You can do this from the extra functions menu.
 
Disk sles11sp2-i386.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x0002d3be
 
             Device Boot      Start         End      Blocks   Id  System
sles11sp2-i386.img1            2048     4208639     2103296   82  Linux swap / Solaris
Partition 1 does not end on cylinder boundary.
sles11sp2-i386.img2   *     4208640    41943039    18867200   83  Linux
Partition 2 has different physical/logical endings:
     phys=(1023, 254, 63) logical=(2610, 212, 34)
[root@jay-linux image]# echo $((4208640*512))
2154823680
[root@jay-linux image]# mount -o loop,offset=2154823680 sles11sp2-i386.img /media
[root@jay-linux image]# cd /media/
[root@jay-linux media]# ls
bin   dev  home  lost+found  mnt  proc  sbin     srv      sys  usr
boot  etc  lib   media       opt  root  selinux  success  tmp  var
[root@jay-linux image]# umount /media/

方法二:用kpartx建立分区映射后,再mount映射后的设备即可,操作实例如下:

[root@jay-linux image]# kpartx -av sles11sp2-i386.img
add map loop3p1 (253:2): 0 4206592 linear /dev/loop3 2048
add map loop3p2 (253:3): 0 37734400 linear /dev/loop3 4208640
 
[root@jay-linux image]# mount /dev/mapper/loop3p2 /media/
 
[root@jay-linux image]# ls /media/
bin   dev  home  lost+found  mnt  proc  sbin     srv      sys  usr
boot  etc  lib   media       opt  root  selinux  success  tmp  var
[root@jay-linux image]# umount /media/
[root@jay-linux image]# mount /dev/mapper/loop3p1 /media/
/dev/mapper/loop3p1 looks like swapspace - not mounted
mount: you must specify the filesystem type
(其中的交换分区,我也还不知道是否可以mount;其实mount交换分区也没意义)
 
(使用完成后,卸载挂载点、删除映射关系即可)
[root@jay-linux image]# umount /media/
[root@jay-linux image]# kpartx -d sles11sp2-i386.img
loop deleted : /dev/loop3

关于LVM的mount,可以参考文末参考资料中的vpsee的文章(我也是试多次没做成功,才偶然看到这篇文章的),我对镜像文件中LVM分区的mount操作如下供参考。

[root@jay-linux image]# fdisk -lu rhel6u2.img
You must set cylinders.
You can do this from the extra functions menu.   Disk rhel6u2.img: 0 MB, 0 bytes
255 heads, 63 sectors/track, 0 cylinders, total 0 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00048b34   Device Boot Start End Blocks Id System
rhel6u2.img1 * 2048 1026047 512000 83 Linux
Partition 1 does not end on cylinder boundary.
rhel6u2.img2 1026048 104857599 51915776 8e Linux LVM
Partition 2 has different physical/logical endings:
phys=(1023, 254, 63) logical=(6527, 21, 22)
[root@jay-linux image]# echo $((1026048*512))
525336576
[root@jay-linux image]# losetup /dev/loop0 rhel6u2.img -o 525336576
[root@jay-linux image]# pvscan
PV /dev/loop0 VG VolGroup lvm2 [49.51 GiB / 0 free]
Total: 1 [49.51 GiB] / in use: 1 [49.51 GiB] / in no VG: 0 [0 ]
[root@jay-linux image]# vgchange -ay VolGroup
2 logical volume(s) in volume group "VolGroup" now active
[root@jay-linux image]# lvs
LV VG Attr LSize Pool Origin Data% Move Log Copy% Convert
lv_root VolGroup -wi-a--- 45.57g
lv_swap VolGroup -wi-a--- 3.94g
[root@jay-linux image]# mount /dev/VolGroup/lv_root /media/
[root@jay-linux image]# ls /media/
bin cgroup etc lib lost+found misc net proc sbin srv tmp var
boot dev home lib64 media mnt opt root selinux sys usr   (使用完后的卸载操作,如下)
[root@jay-linux image]# umount /media/
[root@jay-linux image]# vgchange -an VolGroup
0 logical volume(s) in volume group "VolGroup" now active
[root@jay-linux image]# losetup -d /dev/loop0

mount LVM 分区的 参考资料:

http://www.vpsee.com/2010/10/mount-lvm-volumes-from-loopback-disk-images/

方法二:mount成network block device

参考http://smilejay.com/2012/11/how-to-mount-a-qcow2-image/

1. 首先检查当前系统的kernel对NBD模块的支持(NBD:network block device),加载nbd这个module,如下:

[root@jay-linux kvm_demo]# grep NBD /boot/config-3.5.0
CONFIG_BLK_DEV_NBD=m
[root@jay-linux kvm_demo]# modinfo nbd
filename: /lib/modules/3.5.0/kernel/drivers/block/nbd.ko
license: GPL
description: Network Block Device
srcversion: 56F31584CC2EB73E6F1DA69
depends:
intree: Y
vermagic: 3.5.0 SMP mod_unload modversions
parm: nbds_max:number of network block devices to initialize (default: 16) (int)
parm: max_part:number of partitions per device (default: 0) (int)
parm: debugflags:flags for controlling debug output (int)
[root@jay-linux kvm_demo]# modprobe nbd max_part=16
[root@jay-linux kvm_demo]# lsmod | grep nbd
nbd 7593 0

如果当前kernel没有编译好nbd模块,则需要重新编译该模块(或编译整个kernel),在编译kernel时,“make menuconfig”配置kernel时中选择”Device Drivers –> Block devices –> Network block device support”.
2. 将qcow2镜像映射为网络块设备(nbd),命令如下:

[root@jay-linux kvm_demo]# qemu-nbd -c /dev/nbd0 rhel6u3.qcow2
[root@jay-linux kvm_demo]# ll /dev/nbd0* #这里查看一下
brw-rw---- 1 root disk 43, 0 Nov 1 20:51 /dev/nbd0
brw-rw---- 1 root disk 43, 1 Nov 1 20:51 /dev/nbd0p1
brw-rw---- 1 root disk 43, 2 Nov 1 20:51 /dev/nbd0p2

qemu-nbd工具是:QEMU Disk Network Block Device Server,可以用”qemu-nbd –help”命令查看其帮助信息。

3. 像普通block设备那样使用刚才映射好的网络块设备的分区即可,命令行如下:

[root@jay-linux kvm_demo]# mount /dev/nbd0p1 /mnt/
[root@jay-linux kvm_demo]# cd /mnt/
[root@jay-linux mnt]# ls
bin cgroup etc lib lost+found misc net proc sbin srv tmp var
boot dev home lib64 media mnt opt root selinux sys usr
[root@jay-linux mnt]# cd root/
[root@jay-linux root]# touch nbd-test.txt #这里建立一个文件测试一下,若用这个qcow2 image作为guest启动后也可以看到改文件。

4. 使用完这个qcow2镜像后,卸载已挂载的nbd设备,解除qcow2镜像与nbd设备的关联。

[root@jay-linux kvm_demo]# umount /mnt/
[root@jay-linux kvm_demo]# qemu-nbd -d /dev/nbd0
/dev/nbd0 disconnected

如果你的qcow2文件里面有LVM分区,请参考我如下博客文章的后半部分(关于LVM分区的挂载):

http://smilejay.com/2012/08/mount-an-image-file/

如果想了解Linux上NBD的基本知识,可以查看如下网页:

http://nbd.sourceforge.net/

方法三:libguestfs

http://rwmj.wordpress.com/2010/03/19/gllug-talk-on-libguestfs-18th-march-2010/

Back in 2008 we faced a pressing problem with virtualization. How do we look at what’s going on inside a virtual machine?

如何修改image文件

Let’s step back: what is a virtual machine? In nuts and bolts terms, it’s a big file or partition containing a disk image, and when it’s running, it’s a complicated emulation of CPUs, memory, and virtual devices like network cards. It’s interesting and necessary to be able to look inside all of those things. (“How many packets are coming out of the virtual network card?” “How is the virtual CPU coping with the load?”). But for the purpose of this talk I’m just going to talk about looking inside that disk image.

如何修改image文件

That large (multi-gigabyte) disk image file has a rich internal structure: a Master Boot Record; a boot partition; LVM, which has its own internal structures. Then it contains filesystems and those contain directories and files and more besides.

What might we want to do with the disk image if we could look inside it at this rich internal structure? Clone the machine, changing a few config files like the hostname. Edit grub.conf in a VM which isn’t booting. Audit a VM to find out what licensed software is installed. Is the VM running out of disk space? Offline resizing or backups. Make a new virtual machine from scratch …

如何修改image文件

In 2008 (and now) you could look inside the disk image. First of all you’d need to be root. Then you could run a command line tool called kpartx which splits the disk image partitions into device mapper devices (this is why you need to be root). These are actually global devices on your host, visible to everyone. If you’re lucky, LVM on the host might find the volume groups located in the disk image, but you might have to adjust the global host LVM configuration to get that to work. If you’re unlucky, those could conflict with volume groups already in your host.

So if you are root, you should usually be able to mount a guest disk in the host. If your program crashes, of course, it will leave unattached device mapper devices, loopback devices and mount points on the host system.

It’s not clear from a security point of view if mounting untrusted guest devices on the host as root is a good idea.

That said, kpartx is a useful tool if: you are already root on the host, you just want to mount a partition, it’s ad hoc (no scripting), you can clean up if you make a mistake, and if you can trust the guests.

So we considered how we could improve this process and provide more features.

You shouldn’t need to be root: If you have a word-processor document, you don’t need to be root to edit that document. If you have a JPEG file, you don’t need to run GIMP as root to crop it. So why are disk image files any different? You should be able to modify disk images from CGI scripts, or from shell scripts. You shouldn’t have to clean up after it. There should be no gotchas or corner cases where it doesn’t work.

如何修改image文件

What is libguestfs? An API for creating, accessing, manipulating and modifying filesystems and disk images. Access from many different programming languages, or the command line. A set of useful tools. And applications built on top.

Today is going to be mainly a demonstration of what can be done with libguestfs and the tools we’ve built around this.

[Demonstration of guestfish]

“Guestfish” is the “guest filesystem interactive shell”, and you can just run it on any disk image you happen to find. You don’t need to be root, unless you need root to access that particular image. In this case, the image is just a local file so I don’t need root.

$ guestfish -a disk.img
><fs> run

You can see this image is a Linux virtual machine of some sort.

><fs> cat /etc/fstab
[the fstab from an unidentified Linux machine is shown ...]

We can use the “cat” command to look for some identification:

><fs> cat /etc/motd
><fs> cat /etc/redhat-release
><fs> cat /etc/debian_version
[this shows that it is a Fedora 12 VM]

We can also edit files. For example, we can edit the /etc/issue file to change the console login message:

><fs> vi /etc/issue

Guestfish is the shell-scripting interface to the libguestfs API. It exposes the entire API, and as you can see that’s quite large:

><fs> help

(The full list of commands is here in the manpage).

Since the API is quite daunting, we do offer an overview of the whole API in the man page. So I won’t go through that here.

[Demonstration of using the API from Perl and Python]

This is the Perl example. Notice the use of the Augeas configuration API to pull out the list of NTP servers:

#!/usr/bin/perl -w

use strict;

use Sys::Guestfs;

my $g = Sys::Guestfs->new ();
$g->add_drive_ro ("disk.img");
$g->launch (); my @logvols = $g->lvs ();
print "logical volumes: ", join (", ", @logvols), "\n\n"; $g->mount_ro ("/dev/vg_f12x32/lv_root", "/");
print "----- ISSUE file: -----\n";
print ($g->cat ("/etc/issue"));
print "----- end of ISSUE file -----\n\n"; # Use Augeas to list the NTP servers.
$g->aug_init ("/", 16);
my @nodes = $g->aug_match ("/files/etc/ntp.conf/server");
my @ntp_servers = map { $g->aug_get ($_) } @nodes;
print "NTP servers: ", join (", ", @ntp_servers), "\n\n";

This was the Python example:

#!/usr/bin/python

import guestfs
g = guestfs.GuestFS ()
g.add_drive_ro ("disk.img")
g.launch () parts = g.list_partitions ()
print "disk partitions: %s" % (", ".join (parts))

[Demonstration of guestfish on a Fedora live CD]

We show unpacking a Fedora live CD, as shown before on this blog.

[Demonstration of virt-df]

You can see examples of virt-df output similar to what was demonstrated in the talk.

Virt-df is df for virtual guests. Run the program on the host / dom0 to display disk space used and available on all partitions on all guests.

# virt-df -h
Filesystem Size Used Available Use%
Ubuntu904x64:/dev/sda1 9.4G 2.1G 6.8G 27.7%
Debian5x64:/dev/debian5x64/home 3.4G 761.9M 2.5G 27.0%
Debian5x64:/dev/debian5x64/root 321.5M 111.1M 193.8M 39.7%
Debian5x64:/dev/debian5x64/tmp 302.1M 10.0M 276.5M 8.5%
Debian5x64:/dev/debian5x64/usr 3.4G 1.1G 2.1G 38.3%
Debian5x64:/dev/debian5x64/var 1.7G 612.6M 1001.9M 41.1%
Debian5x64:/dev/sda1 227.9M 18.6M 197.1M 13.5%
F10x32:/dev/VolGroup00/LogVol00 8.8G 3.1G 5.2G 40.3%
F10x32:/dev/sda1 189.9M 20.2M 159.9M 15.8%
CentOS5x32:/dev/VolGroup00/LogVol00 8.6G 3.9G 4.2G 50.6%
CentOS5x32:/dev/sda1 98.7M 23.5M 70.1M 29.0%
Win2003x32:/dev/sda1 20.0G 2.1G 17.9G 10.4%

[Demonstration of virt-inspector]

We demonstrated virt-inspector. You can see earlier examples from this blog here and here.

virt-inspector examines a virtual machine or disk image and tries to determine the version of the operating system and other information about the virtual machine.

Virt-inspector produces XML output for feeding into other programs.

In the normal usage, use virt-inspector -d domname where domnameis the libvirt domain (see: virsh list --all).

You can also run virt-inspector directly on disk images from a single virtual machine. Use virt-inspector -a disk.img. In rare cases a domain has several block devices, in which case you should list several -a options one after another, with the first corresponding to the guest's /dev/sda, the second to the guest's /dev/sdb and so on.

You can also run virt-inspector on install disks, live CDs, bootable USB keys and similar.

[Demonstration of virt-win-reg]

You can see examples of using virt-win-reg on this blog. The infamous Windows Registry sucks posting.

[Demonstration of guestmount]

On this blog, FUSE support for libguestfs and some screenshots showing a Debian guest being mounted on the host.

Example: Mount a Debian guest on the host using FUSE and libguestfs

Example — mount my Debian guest on my host Fedora server, using FUSE support which we added to libguestfs today:

$ mkdir /tmp/rich
$ guestmount $(virt-inspector --ro-fish /dev/vg_trick/Debian5x64) /tmp/rich
$ cat /tmp/rich/etc/debian_version
squeeze/sid
$ cat /tmp/rich/etc/hostname
debian5x64
$ ls -l /tmp/rich/etc/apt/
total 19
-rw-r--r-- 1 root root 51 2009-05-14 18:07 apt.conf
drwxr-xr-x 2 root root 1024 2009-08-13 18:10 apt.conf.d
drwxr-xr-x 2 root root 1024 2009-08-06 14:42 preferences.d
-rw------- 1 root root 0 2009-05-14 18:04 secring.gpg
-rw-r--r-- 1 root root 669 2009-05-24 12:02 sources.list
-rw-r--r-- 1 root root 0 2009-05-14 18:04 sources.list~
drwxr-xr-x 2 root root 1024 2009-02-07 21:18 sources.list.d
-rw------- 1 root root 1200 2009-05-14 18:04 trustdb.gpg
-rw------- 1 root root 5801 2009-05-14 18:04 trusted.gpg
-rw------- 1 root root 5801 2009-05-14 18:04 trusted.gpg~
$ nautilus /tmp/rich/home/rjones/d/libguestfs/

[Demonstration of guestmount and hivexsh]

An example of using hivexsh can be found earlier on this blog.

This was the first talk given using Tech Talk PSE. You can download Tech Talk PSE from the git repository.