我正在尝试找出一种干净且安全的方法来在构建脚本内使用循环设备。据我所知,如果您想要(GPT)分区和(FAT32、EXT3)格式化一个文件,则需要循环设备。疏文件1 .
例如:假设我有这个脚本:
#!/bin/bash
set -ex
truncate --size 4G target.img
sfdisk target.img < partitions
loop_device=$(losetup -f --show target.img)
trap "losetup -d $loop_device" EXIT
partx -u $(loop_device)
mkfs.vfat ${loop_device}p1
mkfs.ext4 ${loop_device}p2
在大多数快乐和不快乐的路径中,循环设备将通过 bash 调用来清理losetup
。但也有一些不愉快的路径2导致循环设备被抛在后面。
如果这是有关挂载的问题,那么简单的解决方案是在挂载名称空间中运行unshare -m
.这将导致内核在进程退出时清理挂载点,而进程不会显式执行相同的操作。
此外,如果循环设备首先是通过挂载创建的,mount -o loop
那么当挂载点存在时,循环设备将被清理,因此通过代理,挂载命名空间也可以用于清理循环设备。
但由于我所追求的是全为零的文件上的 GPT 分区表,因此没有文件系统可以成功安装在其上(据我所知)。
那么,当进程、进程组、命名空间等被清理时,是否有其他方法可以让内核清理循环设备?
- 1 我知道存在解决方案,例如格式化单独的文件,然后使用
dd
偏移量进行复制,但这会导致将多个 GB 的零写入磁盘,而不是保留为稀疏文件。所以这里“稀疏”二字很重要 - 2 一个明显的例子是当 bash 被杀死时会发生什么
kill -9
答案1
losetup -d
惰性地解除关联循环设备,因此可以在不再使用循环设备时立即将其删除。不要捕获,而是打开循环设备的文件描述符并立即取消关联:
#!/bin/bash
set -ex
truncate --size 4G target.img
sfdisk target.img < partitions
loop_device=$(losetup -f --show target.img)
exec 5< "$loop_device"
losetup -d "$loop_device"
partx -u "$loop_device"
mkfs.vfat "${loop_device}p1"
mkfs.ext4 "${loop_device}p2"
当脚本退出时,无论出于何种原因,除了losetup -f
和之间的短窗口外losetup -d
,循环设备都会被清理。