Linux - làm thế nào để định dạng nhiều hệ thống tệp trong một tệp?


9

Tôi cần tạo một hình ảnh đĩa với hai hệ thống tập tin trống. Tôi đã tạo ra nó bằng cách sử dụng

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

Tiếp theo, tôi đã tạo 2 phân vùng chính bằng cách sử dụng fdisk disk.img; một là FAT32 và một là EXT3. Bây giờ, tôi phải định dạng cả hai phân vùng để tạo các hệ thống tệp được gắn kết như -o loop devices. Nhưng tôi không thể hiểu làm thế nào để định dạng chúng? Tôi không thể sử dụng mkfs.vfattrên disk.img. Vì vậy, tôi hoàn toàn bối rối.

GIẢI PHÁP: Nhờ trả lời từ @ pjc50, tôi đã tìm thấy giải pháp rất đơn giản:

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

Một nhược điểm của giải pháp này là yêu cầu về quyền siêu người dùng.


Tôi nghi ngờ rằng tất cả các chương trình đó sẽ có thể sử dụng các phân vùng bên trong một tệp. Bạn có thể tạo hai hệ thống tập tin trong các tệp riêng biệt và sau đó hợp nhất chúng trong một tệp lớn với dd không?
golimar

@golimar: nhưng tôi sẽ cần MBR trên ổ đĩa đó, tôi không biết làm thế nào có thể hợp nhất các hệ thống tệp khác nhau được tạo riêng như các tệp riêng biệt
psihodelia

Bạn có thể sử dụng MBR của tệp gốc mà bạn đã nói. dd cho phép bù đắp với các lệnh 'kích thước' và 'bỏ qua'. Bạn sẽ cần tìm các ngoại lệ và sau đó ghi đè lên một phần của tệp lớn bằng hai tệp nhỏ hơn
golimar

Hãy tha thứ cho tôi nếu tôi ngây thơ ở đây, nhưng tại sao không sử dụng hai tệp riêng biệt?
Garrett

Câu trả lời:


9

Dường như bạn có thể sử dụng các công cụ kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

Kpartx có thể được sử dụng để thiết lập ánh xạ thiết bị cho các phân vùng của bất kỳ thiết bị khối được phân vùng nào. Nó là một phần của công cụ đa luồng Linux. Với kpartx -l imagefile, bạn có được cái nhìn tổng quan về các phân vùng trong tệp hình ảnh và với kpartx -a imagefile, các phân vùng sẽ có thể truy cập qua / dev / mapper / loop0pX (X là số lượng phân vùng). Bạn có thể gắn kết nó ngay bây giờ với mount / dev / mapper / loop0pX / mnt / -o loop, ro. Sau khi ngắt kết nối, bạn có thể ngắt kết nối các thiết bị ánh xạ với tệp hình ảnh kpartx -d.

Tuy nhiên, một nhược điểm của giải pháp này là yêu cầu về quyền siêu người dùng.
psihodelia

1
Tôi nghi ngờ một giải pháp tồn tại mà không yêu cầu quyền siêu người dùng! Đó là, đây là loại hoạt động mà tôi không mong đợi người dùng bình thường có thể thực hiện mà không cần một cơ chế cụ thể được thiết lập trước bởi siêu người dùng (ví dụ: thông qua sudo)
pjc50

2
@ pjc50: có thể thực hiện việc này mà không có quyền siêu người dùng: trước tiên, người ta phải tạo mỗi phân vùng dưới dạng một tệp riêng biệt, sau đó tạo thủ công hình ảnh đĩa và sao chép các phân vùng vào hình ảnh đĩa sau khi tạo bảng phân vùng vào hình ảnh đĩa.
Mikko Rantalainen

1
@MikkoRantalainen chính xác. Dưới đây là một ví dụ có thể chạy tối thiểu: superuser.com/a/1367534/128124
Ciro Santilli 病毒 审查 六四 事件

7

Bạn có thể làm như vậy bằng cách trước tiên gắn các phân vùng của bạn vào /dev/loop?sử dụng losetupvới -otùy chọn để chỉ định một phần bù phù hợp cho phân vùng của bạn. Giá trị bù có thể được tính dựa trên đầu ra của fdisk -l disk.img( start_sector * sector_size).

Ví dụ:

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

Sau khi gắn kết, bạn có thể tiến hành định dạng phân vùng bằng cách sử dụng mkfs.*:

mkfs.vfat -F32 /dev/loop1

Để biết thêm chi tiết và ví dụ, xem các bài viết sau:


Chà, nó không hoạt động :(
psihodelia

@psihodelia Nên. Kết quả là gì nếu bạn làm điều này?
Daniel Beck

Làm thế nào nó không hoạt động? Bạn có mắc lỗi gì không? Bước nào thất bại?
Shawn Chin

$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 tháng 1 năm 2010) Thiết bị vòng không khớp với kích thước đĩa mềm, sử dụng thông số hd mặc định
psihodelia

1
Có thể giúp đỡ nếu bạn chỉ định kích thước khối khi gọi mkfs.vfat. Xem liên kết đầu tiên tôi cung cấp. Cũng được đề cập trong bài viết, cảnh báo đĩa mềm được mong đợi và có thể bỏ qua
Shawn Chin

1

Tôi sẽ đi với các công cụ tôi có trong tâm trí:

  • tạo một VM mới trong Virtualbox với một đĩa, thường là /dev/sda
  • khởi động vào VM với CD Live GParted
  • phân vùng và định dạng đĩa trong VM theo nhu cầu của bạn (2 phân vùng, các hệ thống tệp khác nhau, v.v.)
  • sau đó sử dụng ddđể xuất /dev/sdathành tập tin

Với một phỏng đoán có giáo dục, sẽ mất khoảng 15 phút.


Giải pháp khéo léo thông minh :) Nhưng tôi không tin rằng chỉ mất chưa đến 15 phút. Nhân tiện, thật khó để tự động hóa nó, bởi vì nó yêu cầu người dùng trong giao diện đồ họa (vì vậy, không có kịch bản nào khả thi = không phải là cách Unix).
psihodelia

Sẽ không mất nhiều thời gian :-) vì đĩa ảo nhỏ và không có cài đặt hệ điều hành nào được thực hiện. Phần dài nhất là thời gian khởi động GParted.
karatedog

1

Tối thiểu Runnable sfdisk+ mke2fsví dụ mà khôngsudo

Trong ví dụ này, chúng tôi sẽ tạo, không có sudohoặc setsuid, một tệp hình ảnh có chứa hai phân vùng ext2, mỗi phân vùng chứa các tệp từ một thư mục máy chủ.

Sau đó, chúng tôi sẽ sử dụng sudo losetupchỉ để gắn kết các phân vùng để kiểm tra xem nhân Linux có thực sự có thể đọc chúng như được giải thích tại: /programming/1419361/how-to-mount-one-partition-from-an-image -file-that-chứa-nhiều phân vùng / 39675265 # 39675265

Để biết thêm chi tiết, xem:

Ví dụ:

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

Đã thử nghiệm trên Ubuntu 18.04. GitHub ngược dòng .

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.