分区创建

分区创建

在 Linux 系统上,是否可以仅使用用户空间工具来创建和操作分区映像(可能仅具有 ext2 文件系统),然后使用这些分区映像来创建磁盘映像?

我可以使用genext2fs它在用户空间中生成 ext2 文件系统的映像,但我找不到任何可以操作磁盘映像(例如创建分区表或从现有分区映像创建磁盘映像等)的工具,而无需 root 访问权限。目前,我使用它kpartx来挂载磁盘映像中的分区,但由于这需要 root,因此它实际上并不适合编写脚本,并且如果构建脚本中存在未被捕获的错误,则映射器设备仍处于使用状态。

基本上,我有三个目录,我希望每个目录都成为磁盘映像上的一个分区,但我想编写脚本,而且我真的不想使用任何需要 root 访问权限的工具(似乎这个过程中没有任何内容绝对需要具有 root 访问权限)。

答案1

分区创建

要创建分区表,您可以直接在文件而不是设备上使用常用工具。大多数标准工具都应支持这种用法,例如fdiskpartedparted非常适合集成到脚本中,因为它可以将命令作为参数。

parted -s testing.img mklabel gpt
parted -s -a none testing.img mkpart ESP fat32 0 4M
parted -s -a none testing.img mkpart linux ext4 4M 10M

文件系统创建

我没有一个干净的解决方案来在虚拟分区中安装或创建文件系统。正确的做法可能是fuse为分区表安装一个(用户空间中的文件系统)驱动程序。但目前我还没有找到。

但是,mke2fs可以选择在文件内的任意偏移处-E offset=1234构建ext2ext3ext4文件系统。您可以为其指定分区的偏移量。但是,请确保也为其指定文件系统的大小,因为默认行为似乎存在错误,并默认使用虚拟磁盘的大小编写文件系统,并在需要时扩展文件。

mke2fs -E offset=4000256 testing.img 6316k

不幸的是,并非所有的分区mkfs都有这样的选项。mkfs.vfat所以另一个解决方案是创建一个与分区大小相同的单独文件,使用mkfs它然后dd将内容复制到完整的虚拟磁盘中。

dd if=testing.img of=testing.fat32.img bs=512 skip=34 count=7779
mkfs -t vfat testing.fat32.img
dd if=testing.fat32.img of=testing.img bs=512 seek=34 count=7779 conv=notrunc

虽然不是最干净或最快的解决方案,但它确实有效,非常通用,并且不需要 root 权限。转换选项sparse还可用于通过不写入长零序列来加快速度。

挂载文件系统

您可以在分区中安装文件系统,前提是fuse它支持您的文件系统。ext名称下有对文件系统的标准支持fuse-ext2FAT名称下有对文件系统的标准支持fusefat。不幸的是,他们目前没有选择offset。所以我想你只能使用mountdd与之前相同的技巧。

标准方法使用partxkpartx,(或-o offset选项mount)需要 root 权限。该dd解决方案缓慢、复杂且容易出错。

答案2

我使用并推荐guestfish,它是libguestfs,用于访问和修改虚拟机磁盘映像的库

我发现 OpenStack 的文档包含不需要权限的工具的有用描述:修改图像 — 虚拟机图像指南文档

请注意,如果您进行许多不相交的更改,您可能会受益于运行guestfish守护进程并使用其远程控制模式 - 这可以节省(并非微不足道的)启动时间。

guestfish通过插座进行远程控制手册guestfish

答案3

尝试使用以下组合:

和:

例子:

# Create 1GB sparse file
truncate -s 1G disk1.bin

# Create simple ms-dos partition table an a single partition with maximum free space
echo -e "o\nn\np\n1\n2048\n-1\np\nw\n" | /sbin/fdisk disk1.bin

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.
Be careful before using the write command.

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x4643133c.

Command (m for help): Created a new DOS disklabel with disk identifier 0xff5d1f1e.

Command (m for help): Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): Partition number (1-4, default 1): First sector (2048-2097151, default 2048): Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-2097151, default 2097151): 
Created a new partition 1 of type 'Linux' and of size 1023 MiB.

Command (m for help): Disk disk1.bin: 1 GiB, 1073741824 bytes, 2097152 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
Disklabel type: dos
Disk identifier: 0xff5d1f1e

Device     Boot Start     End Sectors  Size Id Type
disk1.bin  1     2048 2097150 2095103 1023M 83 Linux

Command (m for help): The partition table has been altered.
Syncing disks.

# Check out the offset and size in bytes    
$ parted disk1.bin
GNU Parted 3.3
Using /kvm/test2/disk1/disk1.bin
Welcome to GNU Parted! Type 'help' to view a list of commands.
(parted) unit b                                                           
(parted) p                                                                
Model:  (file)
Disk /kvm/test2/disk1/disk1.bin: 1073741824B
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Disk Flags: 

Number  Start     End          Size         Type     File system  Flags
 1      1048576B  1073741311B  1072692736B  primary  fat32

(parted) q

# Create a placeholder file for fuseloop to use
touch disk1.bin.part1

# fuseloop - take a raw disk image and create a "loopback block device file" for a partition within the raw disk image file
# fuseloop -O OFFSET -S SIZE DISKFILE.RAW PARTITIONFILE.RAW
$ fuseloop -O  1048576  -S 1072692736    disk1.bin   disk1.bin.part1

$ findmnt $(realpath disk1.bin.part1)
TARGET                           SOURCE    FSTYPE OPTIONS
/kvm/test2/disk1/disk1.bin.part1 /dev/fuse fuse   rw,nosuid,nodev,relatime,user_id=0,group_id=0

# Create the filesystem
$ /sbin/mkfs.vfat -n DATA -v disk1.bin.part1
mkfs.fat 4.1 (2017-01-24)
Auto-selecting FAT32 for large filesystem
disk1.bin.part1 has 255 heads and 63 sectors per track,
hidden sectors 0x0000;
logical sector size is 512,
using 0xf8 media descriptor, with 2095103 sectors;
drive number 0x80;
filesystem has 2 32-bit FATs and 8 sectors per cluster.
FAT size is 2048 sectors, and provides 261371 clusters.
There are 32 reserved sectors.
Volume ID is c86be444, volume label DATA       .

# Make a mountpoint dir (please don't use /tmp)
mkdir /tmp/mnt

# fusefat - take the "loopback block device file" and mount it (-o ro or -o rw required)
# fusefat -o MODE PARTITIONFILE.RAW /path/to/mountpoint/
$ fusefat -o ro disk1.bin.part1  /tmp/mnt/

fat type: FAT32. Fsi at 1
Fsioff: 512, size: 512
--- nxtfree --- :4
--- freecnt --- :261368
dataclusters :261371  
first data byte : 2113536 
1st fat off :  16384 
2nd fat off :  1064960
fat_eoc_value: 268435448
fat_eoc_value is eoc?: 1

$ findmnt /tmp/mnt/ 
TARGET    SOURCE  FSTYPE       OPTIONS
/tmp/mnt/ fusefat fuse.fusefat ro,nosuid,nodev,relatime,user_id=0,group_id=0

# Unmount the filesystem (and verify)
$ fusermount -u /tmp/mnt/
$ findmnt /tmp/mnt/ 

# Unmount the "loopback block device file" (and verify)
$ fusermount -u disk1.bin.part1
$ findmnt $(realpath disk1.bin.part1)

相关内容