是否可以在没有 root 权限的情况下在 linux 中创建完整的 SD 映像(即没有环回挂载)?我正在寻找一种自动化嵌入式系统映像创建的方法。映像应包括特定的分区结构和格式化为 FAT 和 ext2 的分区,其中填充了来自构建系统的文件。
5 回答
最小可运行sfdisk
+mke2fs
示例sudo
在这个例子中,我们将创建一个不带sudo
orsetsuid
的映像文件,该文件包含两个 ext2 分区,每个分区都填充了来自主机目录的文件。
然后,我们将sudo losetup
只使用挂载分区来测试 Linux 内核是否可以实际读取它们,如以下所述:如何在 Linux 上从包含多个分区的映像文件中挂载一个分区?
有关更多详细信息,请参阅:
sfdisk
:处理分区表:https ://superuser.com/questions/332252/how-to-create-and-format-a-partition-using-a-bash-script/1132834#1132834mke2fs
:处理分区的 EXT 格式:https ://superuser.com/questions/605196/how-to-create-ext2-image-without-superuser-rights/1366762#1366762
这个例子:
#!/usr/bin/env bash
# Input params.
root_dir_1=root1
root_dir_2=root2
partition_file_1=part1.ext2
partition_file_2=part2.ext2
partition_size_1_megs=32
partition_size_2_megs=32
img_file=img.img
block_size=512
# Calculated params.
mega="$(echo '2^20' | bc)"
partition_size_1=$(($partition_size_1_megs * $mega))
partition_size_2=$(($partition_size_2_megs * $mega))
# Create a test directory to convert to ext2.
mkdir -p "$root_dir_1"
echo content-1 > "${root_dir_1}/file-1"
mkdir -p "$root_dir_2"
echo content-2 > "${root_dir_2}/file-2"
# Create the 2 raw ext2 images.
rm -f "$partition_file_1"
mke2fs \
-d "$root_dir_1" \
-r 1 \
-N 0 \
-m 5 \
-L '' \
-O ^64bit \
"$partition_file_1" \
"${partition_size_1_megs}M" \
;
rm -f "$partition_file_2"
mke2fs \
-d "$root_dir_2" \
-r 1 \
-N 0 \
-m 5 \
-L '' \
-O ^64bit \
"$partition_file_2" \
"${partition_size_2_megs}M" \
;
# Default offset according to
part_table_offset=$((2**20))
cur_offset=0
bs=1024
dd if=/dev/zero of="$img_file" bs="$bs" count=$((($part_table_offset + $partition_size_1 + $partition_size_2)/$bs)) skip="$(($cur_offset/$bs))"
printf "
type=83, size=$(($partition_size_1/$block_size))
type=83, size=$(($partition_size_2/$block_size))
" | sfdisk "$img_file"
cur_offset=$(($cur_offset + $part_table_offset))
# TODO: can we prevent this and use mke2fs directly on the image at an offset?
# Tried -E offset= but could not get it to work.
dd if="$partition_file_1" of="$img_file" bs="$bs" seek="$(($cur_offset/$bs))"
cur_offset=$(($cur_offset + $partition_size_1))
rm "$partition_file_1"
dd if="$partition_file_2" of="$img_file" bs="$bs" seek="$(($cur_offset/$bs))"
cur_offset=$(($cur_offset + $partition_size_2))
rm "$partition_file_2"
# Test the ext2 by mounting it with sudo.
# sudo is only used for testing, the image is completely ready at this point.
# losetup automation functions from:
# https://stackoverflow.com/questions/1419489/how-to-mount-one-partition-from-an-image-file-that-contains-multiple-partitions/39675265#39675265
loop-mount-partitions() (
set -e
img="$1"
dev="$(sudo losetup --show -f -P "$img")"
echo "$dev" | sed -E 's/.*[^[:digit:]]([[:digit:]]+$)/\1/g'
for part in "${dev}p"*; do
if [ "$part" = "${dev}p*" ]; then
# Single partition image.
part="${dev}"
fi
dst="/mnt/$(basename "$part")"
echo "$dst" 1>&2
sudo mkdir -p "$dst"
sudo mount "$part" "$dst"
done
)
loop-unmount-partitions() (
set -e
for loop_id in "$@"; do
dev="/dev/loop${loop_id}"
for part in "${dev}p"*; do
if [ "$part" = "${dev}p*" ]; then
part="${dev}"
fi
dst="/mnt/$(basename "$part")"
sudo umount "$dst"
done
sudo losetup -d "$dev"
done
)
loop_id="$(loop-mount-partitions "$img_file")"
sudo cmp /mnt/loop0p1/file-1 "${root_dir_1}/file-1"
sudo cmp /mnt/loop0p2/file-2 "${root_dir_2}/file-2"
loop-unmount-partitions "$loop_id"
在 Ubuntu 18.04 上测试。GitHub 上游.
you might want to look at genextfs, that creates an ext2 filesystem in a regular file without any sort of mounting.
我遇到了这个问题,找不到可行的解决方案,所以我写了这个我们在这里开源的实用程序。
从自述文件:
$ dd if=/dev/zero of=disk.image bs=1M count=4
4+0 records in
4+0 records out
4194304 bytes (4.2 MB, 4.0 MiB) copied, 0.00470867 s, 891 MB/s
$ parted --script disk.image \
mktable msdos mkpart primary 2048s 100% set 1 boot on
$ mkdir mntdir
$ partfs -o dev=disk.image mntdir
$ mkfs.ext4 mntdir/p1
mke2fs 1.42.13 (17-May-2015)
Creating filesystem with 3072 1k blocks and 768 inodes
Allocating group tables: done
Writing inode tables: done
Creating journal (1024 blocks): done
Writing superblocks and filesystem accounting information: done
$ fusermount -u mntdir
我正在尝试做同样的事情。我的第一次尝试使用了环回块设备,但我发现了需要环回的两个步骤的变通方法。
带环回的步骤
这就是我正在做的事情( $1 是图像文件名,$2 是文件大小):
- 创建归零磁盘映像文件
dd if=/dev/zero of=$1 bs=512 count=$(($2/512))
- 创建分区表
parted -s $1 mklabel msdos
- 创建分区
parted -s $1 "mkpart primary 0% 100%"
- 将分区附加到循环
sudo losetup --find $1 --offset $OFFSET_TO_PARTITION_BYTES
- 使用 mkfs.ext4 制作文件系统
mkfs.ext4 -I 128 -L BOOT -b 2048 -O ^has_journal /dev/loop0 $SIZE_IN_2048_BLOCKS
- 挂载 /dev/loop0
使用环回是因为
- 在第 4 步和第 5 步中,mkfs 没有偏移选项,因此使用 losttup 来解决该问题
- 在第 6 步中,mount 允许使用操作系统的 ext4 驱动程序
环回解决方法
第 4 步和第 5 步的糟糕解决方法:
- xmount --in dd --out vdi disk.img mnt/
- vdfuse -f mnt/disk.vdi -r ./mnt2
- ./mnt2 现在将有两个文件:EntireDisk 和 Partition1
- 将 mkfs.ext4 指向 ./mnt2/Partition1
步骤 6 的变通解决方案:
- 按照步骤 5 的所有步骤解决
- 使用 fuseext2 挂载 ./mnt2/Partition1
警告
警告:他们的文档中没有宣传 ext4 支持,并且尝试安装时会出现警告:
This is experimental code, opening rw a real file system could be
dangerous for your data. Please add "-o ro" if you want to open the file
system image in read-only mode, or "-o rw+" if you accept the risk to test
this module
更新
vdfuse 应该能够在没有 xmount 的帮助下挂载原始映像,但是有一个错误忽略了 RAW 选项。
我在这里用补丁追踪并修复了这个错误:
https://bugs.launchpad.net/ubuntu/+source/virtualbox-ose/+bug/1019075
是的,guestfish 可以做到这一点:
$ cat << END > extlinux.conf
> default linux
> timeout 0
>
> label linux
> kernel /vmlinuz
> append initrd=/initrd.img root=/dev/vda1 rw console=ttyS0
END
$ guestfish -N debian-unstable.img=disk:2G -- \
part-disk /dev/sda mbr : \
part-set-bootable /dev/sda 1 true : \
mkfs ext2 /dev/sda1 : mount /dev/sda1 / : \
tar-in debian-unstable.tar / : \
extlinux / : \
copy-in extlinux.conf /
结果将是debian-unstable.img
一个 ext2 分区,其中包含 tarball 中的所有文件,debian-unstable.tar
并且整个东西都可以使用 extlinux 启动。您可以使用 qemu 验证磁盘映像。