Linux - วิธีการฟอร์แมทระบบไฟล์หลายระบบภายในไฟล์เดียว?


9

ฉันต้องสร้างดิสก์อิมเมจที่มีระบบไฟล์ว่างสองระบบ ฉันสร้างโดยใช้

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

ต่อไปฉันได้สร้าง 2 พาร์ติชั่นหลักโดยใช้fdisk disk.img; หนึ่งคือ FAT32 และอื่น ๆ คือ EXT3 -o loop devicesตอนนี้ผมมีรูปแบบพาร์ทิชันทั้งเพื่อสร้างระบบไฟล์ที่จะติดตั้งเป็น แต่ฉันไม่เข้าใจวิธีการจัดรูปแบบพวกเขา? ฉันไม่สามารถใช้ในการmkfs.vfat disk.imgดังนั้นฉันสับสนโดยสิ้นเชิง

แนวทางแก้ไข: ขอบคุณคำตอบจาก @ pjc50 ฉันพบวิธีแก้ปัญหาที่ง่ายมาก:

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

ข้อเสียของโซลูชันนี้คือข้อกำหนดของสิทธิ์ผู้ใช้ขั้นสูง


ฉันสงสัยว่าโปรแกรมเหล่านั้นทั้งหมดจะสามารถใช้พาร์ติชันภายในไฟล์ได้ คุณสามารถสร้างระบบไฟล์ทั้งสองในไฟล์แยกกันแล้วรวมเข้าเป็นไฟล์ขนาดใหญ่ด้วย dd ได้หรือไม่?
golimar

@ golimar: แต่ฉันต้องการ MBR บนไดรฟ์ฉันไม่รู้ว่ามันเป็นไปได้อย่างไรที่จะรวมระบบไฟล์ต่าง ๆ ที่สร้างขึ้นแยกต่างหากเป็นไฟล์ที่แตกต่าง
psihodelia

คุณสามารถใช้ MBR ของไฟล์ต้นฉบับที่คุณพูด dd อนุญาตให้ออฟเซ็ตด้วยคำสั่ง 'size' และ 'skip' คุณจะต้องค้นหาการชดเชยที่แน่นอนแล้วเขียนทับส่วนของไฟล์ขนาดใหญ่ด้วยไฟล์ที่เล็กกว่าสองรายการ
golimar

ยกโทษให้ฉันถ้าฉันไร้เดียงสาที่นี่ แต่ทำไมไม่ใช้สองไฟล์แยกกันล่ะ
Garrett

คำตอบ:


9

ดูเหมือนว่าคุณสามารถใช้เครื่องมือ kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

Kpartx สามารถใช้เพื่อตั้งค่าการแมปอุปกรณ์สำหรับพาร์ติชันของอุปกรณ์บล็อกพาร์ติชันใด ๆ มันเป็นส่วนหนึ่งของเครื่องมือหลายทาง Linux ด้วย kpartx -l imagefile คุณจะได้รับภาพรวมของพาร์ติชันในไฟล์รูปภาพและด้วย kpartx -a imagefile พาร์ติชันจะสามารถเข้าถึงได้ผ่าน / dev / mapper / loop0pX (X คือจำนวนของพาร์ติชัน) คุณสามารถเมานต์ได้ทันทีด้วย mount / dev / mapper / loop0pX / mnt / -o loop, ro หลังจาก unmounting คุณสามารถยกเลิกการเชื่อมต่ออุปกรณ์ mapper ด้วย kpartx -d imagefile

อย่างไรก็ตามข้อเสียของโซลูชันนี้คือข้อกำหนดของสิทธิ์ผู้ใช้ขั้นสูง
psihodelia

1
ฉันสงสัยว่ามีวิธีแก้ไขปัญหาที่ไม่ต้องการสิทธิ์ผู้ใช้ระดับสูง! นี่คือการเรียงลำดับของการดำเนินการที่ฉันไม่คาดหวังว่าผู้ใช้ปกติจะสามารถทำได้โดยไม่ต้องมีกลไกเฉพาะที่กำหนดโดยผู้ใช้ขั้นสูงล่วงหน้า (เช่นผ่าน sudo)
pjc50

2
@ pjc50: เป็นไปได้ที่จะทำสิ่งนี้โดยไม่มีสิทธิ์ superuser: อันดับแรกต้องสร้างแต่ละพาร์ติชั่นเป็นไฟล์แยกต่างหากจากนั้นสร้างอิมเมจดิสก์ด้วยตนเองและคัดลอกพาร์ติชั่นไปยังอิมเมจดิสก์หลังจากสร้างตารางพาร์ติชันไปยังอิมเมจดิสก์
Mikko Rantalainen

1
@ MikkoRantalainen อย่างแน่นอน นี่คือตัวอย่างที่
รันได้

7

คุณสามารถทำได้โดยติดตั้งพาร์ติชันของคุณก่อนเพื่อ/dev/loop?ใช้losetupกับ-oตัวเลือกเพื่อระบุออฟเซ็ตที่เหมาะสมให้กับพาร์ติชันของคุณ การชดเชยสามารถคำนวณได้ตามผลลัพธ์ของfdisk -l disk.img( start_sector * sector_size)

ตัวอย่างเช่น:

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

เมื่อติดตั้งแล้วคุณสามารถดำเนินการฟอร์แมตพาร์ติชันได้โดยใช้mkfs.*:

mkfs.vfat -F32 /dev/loop1

สำหรับรายละเอียดเพิ่มเติมและตัวอย่างดูบทความต่อไปนี้:


มันไม่ทำงาน :(
psihodelia

@psihodelia มันควร ผลลัพธ์จะเป็นอย่างไรถ้าคุณทำเช่นนี้?
Daniel Beck

มันไม่ทำงานอย่างไร คุณได้รับข้อผิดพลาดหรือไม่? ขั้นตอนใดล้มเหลว
Shawn Chin

$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 ม.ค. 2010) อุปกรณ์วนรอบไม่ตรงกับขนาดฟลอปปี้โดยใช้ hd params เริ่มต้น
psihodelia

1
mkfs.vfatอาจช่วยถ้าคุณระบุขนาดบล็อกเมื่อโทร ดูลิงก์แรกที่ฉันให้ไว้ นอกจากนี้ยังกล่าวถึงในบทความเตือนฟลอปปี้คาดว่าและสามารถละเว้น
Shawn Chin

1

ฉันจะไปกับเครื่องมือที่ฉันมีอยู่ในใจ:

  • สร้าง VM ใหม่ใน Virtualbox ด้วยดิสก์เดียวซึ่งโดยปกติจะเป็น /dev/sda
  • บู๊ตเข้าสู่ VM ด้วย GParted Live CD
  • แบ่งพาร์ติชันและฟอร์แมตดิสก์ใน VM ตามความต้องการของคุณ (2 พาร์ติชันระบบไฟล์ต่าง ๆ ฯลฯ )
  • จากนั้นใช้ddเพื่อส่งออก/dev/sdaไปยังไฟล์

ด้วยการเดาที่มีการศึกษาจะใช้เวลาประมาณ 15 นาที


วิธีแก้ปัญหาที่ชาญฉลาด :) แต่ฉันไม่เชื่อว่ามันใช้เวลาน้อยกว่า 15 นาที อย่างไรก็ตามมันเป็นเรื่องยากที่จะทำให้เป็นอัตโนมัติเพราะต้องการผู้ใช้ในส่วนต่อประสานกราฟิก (ดังนั้นจึงไม่มีสคริปต์ที่เป็นไปได้ = ไม่ใช่วิธี Unix)
psihodelia

ใช้เวลาไม่นาน :-) เนื่องจากดิสก์เสมือนมีขนาดเล็กและไม่มีการติดตั้งระบบปฏิบัติการ ส่วนที่ยาวที่สุดคือเวลาบูต GParted
karatedog

1

ตัวอย่างsfdisk+ ที่รันได้น้อยที่สุดmke2fsโดยไม่มีsudo

ในตัวอย่างนี้เราจะสร้างโดยไม่ต้องsudoหรือsetsuidเป็นไฟล์ภาพที่มีสองพาร์ทิชัน ext2 ประชากรแต่ละคนมีไฟล์จากไดเรกทอรีโฮสต์

จากนั้นเราจะใช้sudo losetupเพื่อติดตั้งพาร์ติชันเพื่อทดสอบว่าเคอร์เนล Linux สามารถอ่านได้จริงตามที่อธิบายไว้ที่: /programming/1419489/how-to-mount-one-partition-from-an-image แฟ้ม: ที่-มี-หลายพาร์ติชั่น / 39675265 # 39675265

สำหรับรายละเอียดเพิ่มเติมโปรดดู:

ตัวอย่าง:

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

ทดสอบกับ Ubuntu 18.04 GitHub ต้นน้ำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.