
我需要用適合腳本/make/自動化的程式碼建立磁碟映像(兩個分割區,一個FAT 檔案系統和一個ext4 檔案系統,用於UEFI/Syslinux USB Linux 開機[作業系統安裝程式],在生產中永遠不會改變)精確(或非常接近)一組任意大小的檔案的大小。換句話說,給定一組構建文件,我需要知道如何生成 FAT 和 ext4 文件系統映像,以及經過分區以保存它們的磁碟映像,其大小經過計算,可導致盡可能接近零的可用空間。稍微多一點空間是可以犯錯的,但兩年後有人向文件添加 N+1 位元組時失敗就不行了。這需要適合 makefile,即反覆試驗並不能解決問題(儘管我認為如果情況變得更糟,帶有閾值的迭代解決方案可能會起作用)。這類似於 ISO-9660 映像(先前的專案中曾使用過該映像,但 Syslinux 不支援 UEFI 上的 ISO-9660 映像)。
我正在使用dd
(分配磁碟映像)、、parted
(dd
分配 FAT 檔案系統)、、mkfs.vfat
(dd
用於 ext4)、、mkfs.ext4
(kpartx
映射分割區)、dd
(寫入 FAT 分割區)、dd
(寫入ext4 分割區),最後dd
將磁碟映像寫入USB以在實際硬體上啟動。
我目前的想法是用來du
確定檔案在建置磁碟上佔用多少空間,然後為額外的檔案系統和分割區開銷以及誤差幅度添加一些餘裕。所以我需要知道dd
給定輸出的每個 的區塊計數du
。
另一個選擇是建立固定大小的大映像,寫入文件,然後將 FAT、ext4 和分割區的大小調整為最小大小。 ext4 檔案系統可以縮小,我看到 FAT 檔案系統也可以縮小。但是,您仍然面臨計算將其縮小到多少的問題。想知道以前是否有人這樣做過,有一些具體的想法(或範例程式碼)。
答案1
我最終使用了軟糖因素和迭代方法的組合(作為故障保護)。這並不需要像我最初設想的那麼複雜。事實證明,目前 FAT 幾乎不需要捏造,但 ext 需要大量的負捏造;由於 ext4 的軟糖係數為零,我有足夠的可用空間(超過 21M)。我轉換為 ext2(誰需要一個臭日誌?!),增加了我的區塊大小,並仔細計算了我需要的 inode,並從中獲得了更多兆位元組的可用空間。我想我可以從 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