
スクリプト/make/自動化に適したコードで、任意のサイズのファイル セットを正確に (または非常に近いサイズに) 保持できるディスク イメージ (UEFI/Syslinux USB Linux ブート [OS インストーラー] 用の 2 つのパーティション、FAT ファイルシステムと ext4 ファイルシステム、本番環境で変更されることはありません) を構築する必要があります。言い換えると、ビルドされたファイル セットが与えられた場合、FAT および ext4 ファイルシステム イメージと、それらを保持するためにパーティション分割されたディスク イメージを生成する方法を知る必要があります。これらのサイズは、空き領域が可能な限りゼロに近くなるように計算されます。少し余裕を持たせても問題ありませんが、2 年後に誰かがファイルに N+1 バイトを追加したときに失敗するのは問題です。これは makefile に適したものである必要があります。つまり、試行錯誤では不十分です (ただし、最悪の場合、しきい値を使用した反復的なソリューションが機能すると思います)。これは ISO-9660 イメージのようなものです (以前のプロジェクトではそうでしたが、Syslinux は UEFI 上の ISO-9660 イメージをサポートしていません)。
私は、dd
(ディスク イメージを割り当てるため)、、parted
( dd
FAT ファイルシステムを割り当てるため)、、mkfs.vfat
( dd
ext4 用)、、(パーティションをマップするため)、mkfs.ext4
( FAT パーティションを書き込むため)、(ext4 パーティションを書き込むため) を使用してファイルを作成し、最後に実際のハードウェアで起動するためにディスク イメージを USB に書き込みます。kpartx
dd
dd
dd
私の現在のアイデアは、 を使用してビルド ディスク上でファイルが占めるスペースの量を判断し、追加のファイル システムとパーティションのオーバーヘッドとエラーのマージンをいくらか追加することです。 そのため、出力が与えられた場合、 のdu
それぞれのブロック数を知る必要があります。 dd
du
もう 1 つのオプションは、固定サイズの大きなイメージを作成し、ファイルを書き込んでから、FAT、ext4、パーティションを最小サイズに変更することです。ext4 ファイルシステムは縮小できますし、FAT ファイルシステムも縮小できるようです。しかし、それでも、どれだけ縮小するかを計算するという問題が残ります。これまでにこれを実行したことがある人や、具体的なアイデア (またはサンプル コード) を持っている人はいないでしょうか。
答え1
結局、私は、ファッジ係数と反復アプローチの組み合わせ (フェイルセーフとして) を使用することにしました。これは、当初私が思い描いていたほど複雑である必要はありません。今のところ、FAT ではほとんどファッジは必要ありませんでしたが、ext では大量のネガティブなファッジが必要でした。ext4 のファッジ係数がゼロの場合、十分な空き領域 (21 MB 以上) がありました。私は ext2 に変換し (誰がジャーナルを必要としますか?!)、ブロック サイズを増やし、必要な inode を慎重に数えて、さらに多くの MB の空き領域を得ました。du から「実際のサイズ」を取得して、そこから計算することもできたと思いますが、たとえ異なるファイルシステムであっても、オーバーヘッドを数える方が近似値に近いだろうと考えました。
# Estimated filesystem overhead, in 512-byte blocks
FS_ESP_FUDGE=256
FS_ISO_FUDGE=-80000 # Wow!
FS_FUDGE_INCR=1024
...
read ESP_RSIZE d < <(du --summarize --block-size=512 $ESP)
read ISO_RSIZE d < <(du --summarize --block-size=512 $ISO)
success=false
until $success; do
let ESP_SIZE=ESP_RSIZE+FS_ESP_FUDGE
let ISO_SIZE=ISO_RSIZE+FS_ISO_FUDGE
let ESP_START=2048
let IMG_SIZE=ESP_SIZE+ISO_SIZE+ESP_START
let ESP_END=ESP_START+ESP_SIZE-1
let ISO_START=ESP_END+1
success=true
...
sudo /sbin/mkfs.vfat /dev/mapper/$p1 -F 16 \
|| error_exit "mkfs.vfat failed" 5
# -N: Count the inodes (all files, plus . and .. for each directory,
# which I can't get "find" to include).
sudo /sbin/mke2fs -b 4096 -N $(( $(find $ISO | wc -l ) + 2 * $(find $ISO -type d | wc -l))) -m 0 -q /dev/mapper/$p2 \
|| error_exit "mke2fs failed" 6
...
if ! tar -C $ESP -c --exclude-vcs --exclude-backups . | \
sudo tar -C mnt/esp -x; then
{
read
read fs onek used avail use rest
} < <(df mnt/esp)
# Are we out of disk space? If not, bail, else increase margin, retry
[[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \
error_exit "esp tar failed" 9
let FS_ESP_FUDGE=FS_ESP_FUDGE+FS_FUDGE_INCR
success=false
fi
if ! tar -C $ISO -c --exclude-vcs --exclude-backups . | \
sudo tar -C mnt/iso --owner=root --group=root -x ; then
{
read
read fs onek used avail use rest
} < <(df mnt/iso)
# Are we out of disk space? If not, bail, else increase margin, retry
[[ $onek -ne $used || $avail -ne 0 || $use != "100%" ]] && \
error_exit "iso tar failed" 10
let FS_ISO_FUDGE=FS_ISO_FUDGE+FS_FUDGE_INCR
success=false
fi
$success || echo "Whoops, I guessed too small; please adjust fudge factor. Retrying ..."
...
done