从 tarball 生成 .img:/dev/loop 设备

从 tarball 生成 .img:/dev/loop 设备

我正在尝试使用我找到的以下脚本从 tarball 制作 .img:

#!/bin/bash

# Packages required
# dosfstools parted 
# Can be run on any Linux system
# loop.max_part=15 must be in kernel cmdline (cmdline.txt for rpi)
# then reboot

echo "creating image to fit on 2Gb card"
dd if=/dev/zero of=arch-rpi.img bs=1M count=1850

echo "Partitioning"
fdisk arch-rpi.img <<EOF
o
n
p
1

+100M

t
c
n
p
2


w
EOF

sleep 5

losetup -f arch-rpi.img
sleep 5

echo "Formatting vfat"
mkfs.vfat /dev/loop0p1
sleep 5
mkdir boot
echo "Mounting boot"
mount /dev/loop0p1 boot
echo "Installing"

echo "Formatting ext4"
mkfs.ext4 /dev/loop0p2
sleep 5
mkdir root
echo "Mounting root"
mount /dev/loop0p2 root

wget http://archlinuxarm.org/os/ArchLinuxARM-rpi-latest.tar.gz
echo "Installing"
bsdtar -xpf ArchLinuxARM-rpi-latest.tar.gz -C root
sync
mv root/boot/* boot
sync
umount boot root
losetup -d /dev/loop0p1
losetup -d /dev/loop0p1
losetup -d /dev/loop0
echo "All complete, image arch-rpi.img created, compressing...."
zip -9 arch-rpi.img.zip arch-rpi.img

我正在我的 Raspberry Pi - Raspbian Wheezy 上执行此操作。当它到达该行时,mkfs.vfat /dev/loop0p1它说没有这样的文件/目录。我已经在 Linux 上阅读了足够多的内容,知道我正在尝试将 .img 安装为循环设备,然后使用 mkfs 为 tarball 准备图像,但我不太清楚为什么不存在 Loop0p# 文件,它们由 列出fdisk -l。我需要做什么才能让我发现的这个脚本正常工作?

答案1

您需要用于losetup -P创建-P分配的循环设备,否则您需要对原始循环设备进行分区,然后partx -u更新内核的分区表。设备/dev/loop0p将出现内核识别出该分区实际上已被分区。也许这部分是其背后的意图sleep 5- 但几乎肯定应该是一个sync- 或两者兼而有之。

无论如何,为了证明:

sudo sh -s <<\IN
    losetup -D                          
    fallocate "-l$((1024*1024*1024))" loop        
    printf %s\\n n '' '' '' ''  w y | gdisk loop
    sync; losetup -f loop
    lsblk /dev/loop*
IN

所以上面的序列首先-D蚀刻所有电流环路设备(如果有的话) fallocatesa 1GB tmp 文件,向其写入 GPT 分区表并对其进行单个分区,然后sync创建文件系统并将其分配给-f第一个可用的循环设备,然后尝试列出lsblk所有可用的循环设备。它打印:

NAME  MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
loop0   7:0    0   1G  0 loop 

如果我将该losetup行更改为:

losetup -fP loop

...它改为打印:

NAME      MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0       7:0    0    1G  0 loop 
├─loop0p1 259:0    0 1023M  0 loop 
└─loop0p2 259:1    0 1007K  0 loop 

...因为losetup首先扫描备份文件中的分区表。正如你所看到的,它并不是很擅长——而不是注意到额外的 1M(实际上,这几乎肯定是最后一次迭代的分区表)作为未分配的空间,它将其解释为一个单独的分区,但这可能是因为我正在写入 tmpfs(连续两次)在 1GB 文件洞的顶部 - 使用实际数据进行工作会更加精确(并将支持文件清零,就像您的脚本所做的那样,dd无论如何都会处理这个问题)。无论如何 - 我可以自由地mkfs.whatever在真正的分区上然后mount它。partx -u/dev/loop0会达到相同的结果。

答案2

在驱动程序中,对分区的支持是可选的,由加载驱动程序时的参数loop决定。max_part默认值为 0,因此循环驱动程序甚至不会查找分区;如果值为非零,则驱动程序支持那么多分区。根据内核构建选项,驱动程序可能包含在内核中,在这种情况下,您需要loop.max_part=…在引导时传递内核命令行,或者作为模块加载,在这种情况下,您需要max_part=…在模块启动时传递已加载。

在 Debian 上 wheezyloop是一个模块,max_part参数未传递。要获得分区支持,请卸载模块并使用参数将其加载回来max_part(您需要首先使用 停用任何现有的循环设备losetup -d):

if lsmod | grep -wq loop; then rmmod loop; fi
modprobe loop max_part=31

您可以通过添加到options loop max_part=31来将其设置为默认值/etc/modprobe.conf

如果您无法卸载模块(或者在loop内核内置的发行版上重新启动),您可以手动计算分区的偏移量并-o使用losetup.看 从整个磁盘映像读取文件系统

使用较新的发行版,losetup -P您可以在设置循环设备时使用:


losetup -P -f arch-rpi.img

但是util-linuxDebian wheezy 上的软件包太旧了,没有这个选项。

相关内容