Linux - como formatar vários sistemas de arquivos em um arquivo?

9

Preciso criar uma imagem de disco com dois sistemas de arquivos vazios. Eu o criei usando

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

Em seguida, criei 2 partições principais usando fdisk disk.img; um é FAT32 e o outro é EXT3. Agora, tenho que formatar as duas partições para criar sistemas de arquivos para serem montados como -o loop devices. Mas não consigo entender como formatá-los? Eu não posso usar mkfs.vfatno disk.img. Então, eu estou totalmente confuso.

SOLUÇÃO: Graças à resposta da @ pjc50, encontrei uma solução muito simples:

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

Uma desvantagem desta solução é a exigência de direitos de superusuário.

psihodelia
fonte
Duvido que todos esses programas possam usar partições dentro de um arquivo. Você pode criar os dois sistemas de arquivos em arquivos separados e depois mesclá-los em um arquivo grande com o dd?
golimar 12/12
@golimar: mas vou precisar MBR nesta unidade, eu não sei como é possível mesclar diferentes sistemas de arquivos criados separadamente como arquivos distintos
psihodelia
Você pode usar o MBR do arquivo original que você disse. O dd permite compensações com os comandos 'size' e 'skip'. Você precisa encontrar os deslocamentos cobra e parte em seguida, de substituição do arquivo grande com os dois menores
Golimar
Perdoe-me se estou sendo ingênuo aqui, mas por que não usar apenas dois arquivos separados?
Garrett

Respostas:

9

Parece que você pode usar as ferramentas do kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

O Kpartx pode ser usado para configurar mapeamentos de dispositivos para as partições de qualquer dispositivo de bloco particionado. Faz parte das ferramentas multipath do Linux. Com o kpartx -l imagefile, você obtém uma visão geral das partições no arquivo de imagem e com o kpartx -a imagefile as partições estarão acessíveis via / dev / mapper / loop0pX (X é o número da partição). Você pode montá-lo agora com mount / dev / mapper / loop0pX / mnt / -o loop, ro. Após a desmontagem, você pode desconectar os dispositivos mapeadores com o kpartx -d imagefile.
pjc50
fonte
No entanto, uma desvantagem desta solução é a exigência de direitos de superusuário.
Pshodelia
11
Duvido que exista uma solução que não exija direitos de superusuário! Ou seja, este é o tipo de operação não espero que usuários normais para ser capaz de fazer sem um mecanismo específico criado pelo super usuário com antecedência (por exemplo, através sudo)
pjc50
2
@ pjc50: é possível fazer isso sem direitos de superusuário: é preciso primeiro criar cada partição como um arquivo separado, depois criar manualmente a imagem do disco e copiar as partições na imagem do disco após criar a tabela de partições na imagem do disco.
Mikko Rantalainen
11
@MikkoRantalainen exatamente. Aqui está um exemplo mínimo de executável: superuser.com/a/1367534/128124
Ciro Santilli escreveu:
7

Você pode fazer isso primeiro montando suas partições para /dev/loop?usar losetupcom a -oopção de especificar um deslocamento adequado para sua partição. O deslocamento pode ser calculado com base na saída de fdisk -l disk.img( start_sector * sector_size).

Por exemplo:

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

Depois de montada, você pode prosseguir para formatar a partição usando mkfs.*:

mkfs.vfat -F32 /dev/loop1

Para mais detalhes e exemplos, consulte os seguintes artigos:

Shawn Chin
fonte
Bem, ele não funciona :(
psihodelia
@psihodelia Deveria. Qual é o resultado se você fizer isso?
Daniel Beck
Como isso não funciona? Voce encontrou um erro? Qual etapa falha?
Shawn Chin
$ Sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 Jan 2010) dispositivo de loop não coincide com um tamanho de disquetes, usando parâmetros hd padrão
psihodelia
11
Pode ajudar se você especificar o tamanho do bloco ao ligar mkfs.vfat. Veja o primeiro link que forneci. Também mencionado no artigo, o aviso de disquete é esperado e pode ser ignorado
Shawn Chin
1

Eu iria com as ferramentas que tenho em mente:

  • crie uma nova VM no Virtualbox com um disco, que normalmente seria /dev/sda
  • inicialize na VM com um Live CD GParted
  • particione e formate o disco na VM de acordo com suas necessidades (2 partições, diferentes sistemas de arquivos etc.)
  • em seguida, use dda exportação /dev/sdapara um arquivo

Com um palpite, levaria cerca de 15 minutos.

karatedog
fonte
Solução complicada inteligente :) Mas não acredito que demore menos de 15 minutos. A propósito, é difícil automatizá-lo, porque requer um usuário em uma interface gráfica (portanto, nenhum script é possível = não é um modo Unix).
Pshodelia
Não demora muito :-) porque o disco virtual é pequeno e não é feita nenhuma instalação do SO. A parte mais longa é o tempo de inicialização do GParted.
karatedog
1

Executável mínimo sfdisk+ mke2fsexemplo semsudo

Neste exemplo, criaremos, sem sudoou setsuid, um arquivo de imagem que contém duas partições ext2, cada uma preenchida com arquivos de um diretório host.

Em seguida, usaremos sudo losetupapenas para montar as partições para testar se o kernel do Linux pode realmente lê-las, conforme explicado em: /programming/1419489/how-to-mount-one-partition-from-an-image -arquivo-que-contém-múltiplas-partições / 39675265 # 39675265

Para mais detalhes, consulte:

O exemplo:

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

Testado no Ubuntu 18.04. GitHub upstream .

Ciro Santilli adicionou uma nova foto
fonte