Linux - bagaimana memformat banyak sistem file dalam satu file?

9

Saya perlu membuat image disk dengan dua sistem file kosong. Saya telah membuatnya menggunakan

dd if=/dev/zero of=./disk.img bs=1MiB count=1024

Selanjutnya, saya telah membuat 2 partisi primer menggunakan fdisk disk.img; satu adalah FAT32 dan lainnya adalah EXT3. Sekarang, saya harus memformat kedua partisi untuk membuat sistem file yang akan di-mount -o loop devices. Tetapi saya tidak mengerti bagaimana memformatnya? Saya tidak dapat menggunakan mkfs.vfatpada disk.img. Jadi saya benar-benar bingung.

SOLUSI: Terima kasih atas jawaban dari @ pjc50, saya menemukan solusi yang sangat sederhana:

sudo aptitude install multipath-tools
sudo kpartx -a disk.img   #it maps (mounts) found partitions to /dev/mapper/loop...
sudo mkfs.vfat -F 32 -n boot /dev/mapper/loop0p1
sudo mkfs.ext3 -L rootfs /dev/mapper/loop0p2

Kelemahan dari solusi ini adalah persyaratan hak pengguna super.

psihodelia
sumber
Saya ragu bahwa semua program itu akan dapat menggunakan partisi di dalam file. Bisakah Anda membuat dua filesystem dalam file terpisah dan kemudian menggabungkannya dalam file besar dengan dd?
golimar
@ Gimar: tetapi saya akan membutuhkan MBR pada drive tersebut, saya tidak tahu bagaimana mungkin untuk menggabungkan filesystem yang berbeda yang dibuat secara terpisah sebagai file yang berbeda
psihodelia
Anda dapat menggunakan MBR dari file asli yang Anda katakan. dd memungkinkan offset dengan perintah 'ukuran' dan 'lewati'. Anda perlu menemukan offset yang tepat dan kemudian menimpa bagian dari file besar dengan dua yang lebih kecil
golimar
Maafkan saya jika saya naif di sini, tetapi mengapa tidak hanya menggunakan dua file terpisah?
Garrett

Jawaban:

9

Tampaknya Anda dapat menggunakan alat kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

Kpartx dapat digunakan untuk mengatur pemetaan perangkat untuk partisi perangkat blok yang dipartisi. Ini adalah bagian dari Linux multipath-tools. Dengan kpartx -l imagefile Anda mendapatkan gambaran umum dari partisi dalam file gambar dan dengan kpartx -a imagefile partisi akan dapat diakses melalui / dev / mapper / loop0pX (X adalah jumlah partisi). Anda dapat memasangnya sekarang dengan mount / dev / mapper / loop0pX / mnt / -o loop, ro. Setelah melepas, Anda dapat memutuskan perangkat mapper dengan filefile kpartx -d.
pjc50
sumber
Namun, kelemahan dari solusi ini adalah persyaratan hak pengguna super.
psihodelia
1
Saya ragu ada solusi yang tidak memerlukan hak pengguna super! Yaitu, ini adalah jenis operasi yang saya tidak harapkan agar pengguna normal dapat melakukannya tanpa mekanisme khusus yang dibuat oleh pengguna super sebelumnya (misalnya melalui sudo)
pjc50
2
@ pjc50: dimungkinkan untuk melakukan ini tanpa hak pengguna super: pertama-tama seseorang harus membuat setiap partisi sebagai file yang terpisah, kemudian secara manual membuat disk image dan menyalin partisi ke disk image setelah membuat tabel partisi ke disk image.
Mikko Rantalainen
1
@MikkoRantalainen tepatnya. Berikut adalah contoh runnable minimal: superuser.com/a/1367534/128124
Ciro Santilli 冠状 病毒 审查 六四 事件 事件
7

Anda dapat melakukannya dengan terlebih dahulu memasang partisi Anda untuk /dev/loop?menggunakan losetupdengan -oopsi untuk menentukan offset yang sesuai untuk partisi Anda. Offset dapat dihitung berdasarkan output dari fdisk -l disk.img( start_sector * sector_size).

Sebagai contoh:

losetup -o32256 /dev/loop1 ./disk.img   # mount first partition

Setelah dipasang, Anda kemudian dapat melanjutkan untuk memformat partisi menggunakan mkfs.*:

mkfs.vfat -F32 /dev/loop1

Untuk detail dan contoh lebih lanjut, lihat artikel berikut:

Shawn Chin
sumber
Yah, itu tidak berhasil :(
psihodelia
@psihodelia Seharusnya. Apa hasilnya jika Anda melakukan ini?
Daniel Beck
Bagaimana cara kerjanya? Apakah Anda mendapatkan kesalahan? Langkah mana yang gagal?
Shawn Chin
$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 Jan 2010) Perangkat loop tidak cocok dengan ukuran floppy, menggunakan params hd standar
psihodelia
1
Mungkin bisa membantu jika Anda menentukan ukuran blok saat menelepon mkfs.vfat. Lihat tautan pertama yang saya berikan. Disebutkan juga dalam artikel tersebut, peringatan floppy diharapkan dan dapat diabaikan
Shawn Chin
1

Saya akan menggunakan alat yang ada dalam pikiran saya:

  • buat VM baru di Virtualbox dengan satu disk, itu biasanya /dev/sda
  • boot ke VM dengan Live CD GParted
  • mempartisi dan memformat disk dalam VM sesuai kebutuhan Anda (2 partisi, sistem file yang berbeda, dll.)
  • lalu gunakan dduntuk mengekspor /dev/sdake file

Dengan tebakan yang berpendidikan, dibutuhkan sekitar 15 menit.

karatedog
sumber
Solusi rumit yang cerdas :) Tapi saya tidak percaya itu membutuhkan waktu kurang dari 15 menit. Ngomong-ngomong, sulit untuk mengotomatiskannya, karena memerlukan pengguna dalam antarmuka grafis (jadi, tidak ada skrip yang mungkin = bukan cara Unix).
psihodelia
Tidak butuh waktu lama :-) karena disk virtual kecil, dan tidak ada instalasi OS yang dilakukan. Bagian terpanjang adalah waktu boot GParted.
karatedog
1

Minimal runnable sfdisk+ mke2fscontoh tanpasudo

Dalam contoh ini, kita akan membuat, tanpa sudoatau setsuid, file gambar yang berisi dua partisi ext2, masing-masing diisi dengan file dari direktori host.

Kami kemudian akan menggunakan sudo losetuphanya untuk memasang partisi untuk menguji bahwa kernel Linux benar-benar dapat membacanya seperti yang dijelaskan di: /programming/1419489/how-to-mount-one-partition-from-an-image -file-that-berisi-multi-partisi / 39675265 # 39675265

Untuk detail lebih lanjut, lihat:

Contoh:

#!/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:
# /programming/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"

Diuji pada Ubuntu 18.04. GitHub hulu .

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
sumber