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

Недостатком этого решения является требование прав суперпользователя.

psihodelia
источник
Я сомневаюсь, что все эти программы смогут использовать разделы внутри файла. Можете ли вы создать две файловые системы в отдельных файлах, а затем объединить их в большой файл с помощью dd?
Голимар
@golimar: но мне понадобится MBR на таком диске, я не знаю, как можно объединить разные файловые системы, созданные отдельно, в отдельные файлы
psihodelia
Вы можете использовать MBR оригинального файла, который вы сказали. dd допускает смещения с помощью команд «size» и «skip». Вам нужно будет найти точные смещения, а затем переписать часть большого файла двумя меньшими
golimar 12.12.11
Простите, если я здесь наивен, но почему бы не использовать два отдельных файла?
Гаррет

Ответы:

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 - номер раздела). Вы можете смонтировать его сейчас с помощью монтирования / dev / mapper / loop0pX / mnt / -o loop, ro. После размонтирования вы можете отключить устройства отображения с помощью kpartx -d imagefile.
pjc50
источник
Однако недостатком этого решения является требование прав суперпользователя.
Психоделия
1
Я сомневаюсь, что существует решение, которое не требует прав суперпользователя! То есть, это такая операция, которую я не ожидаю, что обычные пользователи смогут обойтись без определенного механизма, заранее настроенного суперпользователем (например, с помощью sudo)
pjc50
2
@ pjc50: это можно сделать без прав суперпользователя: сначала необходимо создать каждый раздел в виде отдельного файла, затем вручную создать образ диска и скопировать разделы в образ диска после создания таблицы разделов в образе диска.
Микко Ранталайнен
1
@MikkoRantalainen точно. Вот минимальный работоспособный пример: superuser.com/a/1367534/128124
Сиро Сантилли 冠状 法轮功 审查 六四 事件 法轮功
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 Должен. Каков результат, если вы сделаете это?
Даниэль Бек
Как это не работает? Вы получаете ошибку? Какой шаг не удался?
Шон Чин
$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 января 2010) Устройство лупа не соответствует размеру дискеты, используя параметры hd по умолчанию
psihodelia
1
Может помочь, если вы укажете размер блока при вызове mkfs.vfat. Смотрите первую ссылку, которую я предоставил. Также упоминается в статье, предупреждение дискеты ожидается и может быть проигнорировано
Шон Чин
1

Я бы пошел с инструментами, которые я имею в виду:

  • создайте новую виртуальную машину в Virtualbox с одним диском, который обычно /dev/sda
  • загрузиться в виртуальную машину с GParted Live CD
  • разбить и отформатировать диск в виртуальной машине в соответствии с вашими потребностями (2 раздела, различные файловые системы и т. д.)
  • затем использовать ddдля экспорта /dev/sdaв файл

С обоснованным предположением это займет около 15 минут.

karatedog
источник
Умное хитрое решение :) Но я не верю, что это займет не более 15 минут. Между прочим, это трудно автоматизировать, потому что для этого требуется пользователь в графическом интерфейсе (так что никакой сценарий невозможен = не Unix-способ).
Психоделия
Это не займет много времени :-), потому что виртуальный диск маленький, и установка ОС не производится. Самая длинная часть - это время загрузки GParted.
karatedog
1

Минимальный пробег sfdisk+ mke2fsпример безsudo

В этом примере мы создадим, без sudoили setsuid, файл образа, который содержит два раздела ext2, каждый из которых заполнен файлами из каталога хоста.

Затем мы будем использовать sudo losetupтолько для монтирования разделов, чтобы проверить, что ядро ​​Linux действительно может их прочитать, как описано по адресу: /programming/1419489/how-to-mount-one-partition-from-an-image -file-содержащий многодисковые разделы / 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 вверх по течению .

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
источник