Como formatar uma partição dentro de um arquivo img?


12

Criei um imgarquivo através do seguinte comando:

dd if=/dev/zero bs=2M count=200 > binary.img

É apenas um arquivo com zeros, mas posso usá-lo fdiske criar uma tabela de partição:

# fdisk binary.img

Device does not contain a recognized partition table.
Created a new DOS disklabel with disk identifier 0x51707f21.

Command (m for help): p
Disk binary.img: 400 MiB, 419430400 bytes, 819200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x51707f21

e, digamos, uma partição:

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1): 
First sector (2048-819199, default 2048): 
Last sector, +sectors or +size{K,M,G,T,P} (2048-819199, default 819199): 

Created a new partition 1 of type 'Linux' and of size 399 MiB.

Command (m for help): w
The partition table has been altered.
Syncing disks.

Quando verifico a tabela de partição, obtenho o seguinte resultado:

Command (m for help): p
Disk binary.img: 400 MiB, 419430400 bytes, 819200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disklabel type: dos
Disk identifier: 0x7f3a8a6a

Device      Boot Start    End Sectors  Size Id Type
binary.img1       2048 819199  817152  399M 83 Linux

Portanto, a partição existe. Quando tento formatar esta partição via gparted, recebo o seguinte erro:

insira a descrição da imagem aqui

Não sei por que ele procura binary.img1e não tenho idéia de como formatar a partição a partir do comando live.

Alguém sabe como formatá-lo usando o sistema de arquivos ext4?


2
Uma opção é executar o truque de losetup a partir desta resposta e, em seguida, executar mkfs.ext4 no dispositivo de loopback.
Miikka

Encontrei este link unix.stackexchange.com/a/87189/52763 . E é isso que eu queria. O problema é que, quando verifico o dispositivo no gparted, recebo Couldn't find valid filesystem superblock.. Aqui está a foto: i.imgur.com/dl7XAC4.png . Isso é algum tipo de bug?
Mikhail Morfikov

Respostas:


13

Você pode acessar a imagem do disco e suas partições individuais através do recurso de loopback. Você já descobriu que alguns utilitários de disco funcionarão (razoavelmente) alegremente nas imagens de disco. No entanto, mkfsnão é um deles (mas estranhamente mounté).

Aqui é produzido a partir de fdisk -lu binary.img:

Disk binary.img: 400 MiB, 419430400 bytes, 819200 sectors
Units: sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
...

Device           Boot Start    End Sectors  Size Id Type
binary.img1            2048 819199  817152  399M 83 Linux

Para acessar a partição que você criou, você tem algumas opções

  1. A rota explícita

    losetup --offset $((512*2048)) --sizelimit $((512*817152)) --show --find binary.img
    /dev/loop0
    

    A saída /dev/loop0é o nome do dispositivo de loop que foi alocado. O --offsetparâmetro é apenas o deslocamento da partição ( Start) multiplicado pelo tamanho do setor ( 512). Considerando que --sizelimité o tamanho da partição, e você pode calculá-lo da seguinte maneira: End-Start + 1, que é 819199-2048 + 1 = 817152, e esse número também deve ser multiplicado pelo tamanho do setor.

    Você pode usar /dev/loop0como referência à partição:

    mkfs -t ext4 -L img1 /dev/loop0
    mkdir -p /mnt/img1
    mount /dev/loop0 /mnt/img1
    ...
    umount /mnt/img1
    losetup -d /dev/loop0
    
  2. A rota implícita

    losetup --partscan --show --find binary.img
    /dev/loop0
    

    A saída /dev/loop0é o nome do dispositivo de loop primário que foi alocado. Além disso, a --partscanopção diz ao kernel para procurar no dispositivo uma tabela de partição e atribuir dispositivos de loop subsidiários automaticamente. No seu caso, com a única partição que você também obtém /dev/loop0p1, que você pode usar como referência à partição:

    mkfs -t ext4 -L img1 /dev/loop0p1
    mkdir -p /mnt/img1
    mount /dev/loop0p1 /mnt/img1
    ...
    umount /mnt/img1
    losetup -d /dev/loop0
    

@ Mikhail curioso para ver que você calculou o tamanho da partição quando ela já foi fornecida como parte da fdisksaída.
roaima

2
O que há de errado com algumas matemáticas? Além disso, é bom saber que você pode facilmente obter o número do setor direito dessa forma, apenas no caso ...
Mikhail Morfikov

Apenas uma observação rápida: "o frontend do mkfs está obsoleto em favor dos mkfs específicos do sistema de arquivos. <type> utils", citados nas páginas de manual do mkfs.
gmagno 21/02

@ gmagno está correto agora, certamente. Mas, tanto quanto eu posso determinar sem cavar por muito tempo ou muito tempo, esse aviso foi lançado pela primeira vez com o util-linux 2.25-rc1, e que não chegou ao Debian estável até muito tempo depois de junho de 2015. Sinta-se livre para atualizar a resposta com informações atuais.
roaima 21/02

11

Existe outra maneira de fazer isso em geral, use kpartx( não relacionado ao kde)

sudo kpartx -a binary.img

e agora você deve ter todos os dispositivos de partições definidas em /dev/mappercomo loop0p1 , loop0p2 , ...

e depois

sudo mkfs.ext4 /dev/mapper/loop0p1

Opcionalmente, quando terminar, você também pode executar

sudo kpartx -d binary.img

se livrar do loop0p? deduzir


2
Não sei por que isso não tem mais votos. IMO é a melhor resposta ...!
Jeremy Davis

Funciona com partições GPT, por exemplo, se você deseja modificar a partição EFI de um dd de disco inteiro.
Russ

3

Eu não sei por que ele procura binary.img1

(… E depois para binary.img2enterrado no comentário).

Isso ocorre porque as ferramentas esperam que os nomes dos arquivos sigam um padrão específico. Esse padrão é aquele usado pelos arquivos do dispositivo para discos e volumes de disco reais no seu sistema, a saber:

  • Um arquivo de dispositivo que abrange todo o disco é nomeado sda(ou outra coisa). É isso que fdiskespera fazer uso.
  • Arquivos de dispositivos para fatias individuais do disco, descrito por seu particionamento, são nomeados sda1, sda2, sda3, e assim por diante. É disso que ferramentas, como as gpartedesperadas, devem usar quando mandam mkfsfazer coisas em volumes de discos individuais .

Obviamente, os arquivos comuns não se sobrepõem da mesma maneira que os arquivos dos dispositivos de disco. As discussões envolvendo o sistema de arquivos de auto-retorno que você tem visto são todos sobre a tomada de uma única imagem-disco inteiro e usando auto-retorno para criar as 1, 2, 3, e assim por diante arquivos que refletem as fatias individuais dentro dele, uma vez que o layout da partição desejado foi escrito para a tabela de partição.


Isso faz sentido!
Mikhail Morfikov

0

Embora este tópico não esteja diretamente relacionado, ele menciona muitas informações iguais e relacionadas.

Wiki Debian | Raspberry Pi e qemu-user-static

Se você não pode aptinstalar alguns dos comandos mencionados nesta postagem, tente usar apt-cache search [package_name]. Isso pode não gerar nenhum resultado se o comando vier de um pacote com um nome diferente.

Por exemplo, losetupanteriormente poderia ser instalado como losetupusado apt install losetup, mas agora faz parte util-linuxdo repositório do Ubuntu. Para descobrir qual pacote atua como um contêiner para outro pacote, você deve usar a pesquisa do repositório online para sua distribuição Linux. Ou, se você precisar instalá-lo de outra fonte, use um mecanismo de pesquisa na Web.

Vale a pena conferir alguns pacotes ...

util-linux genisoimage dosfstools squashfs-tools fsarchiver xfsprogs reiserfsprogs reiser4progs jfsutils ntfsprogs btrfs-tools

Toda distribuição Linux também possui suas próprias páginas de manual online. Às vezes, é mais fácil usar as páginas de manual do que um tutorial. As páginas do manual também informarão todas as opções e parâmetros de comando. Um tutorial geralmente se concentrará apenas nos usados.


0

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 .

Auxiliar para agrupar um arquivo de sistema de arquivos brutos existente em uma imagem

Extraído do exposto, o seguinte pode ser útil:

# Put a raw filesystem file into a disk image with a partition table.
#
# /unix/209566/how-to-format-a-partition-inside-of-an-img-file/527132#527132
#
# Usage:
#
#     sfdisk-fs-to-img root.ext2
#
# Creates a file:
#
#     sfdisk-fs-to-img root.ext2.img
#
sfdisk-fs-to-img() (
  partition_file_1="$1"
  img_file="${partition_file_1}.img"
  block_size=512
  partition_size_1="$(wc -c "$partition_file_1" | awk '{print $1}')"
  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)/$bs)) skip="$(($cur_offset/$bs))"
  printf "
  type=83, size=$(($partition_size_1/$block_size))
  " | sfdisk "$img_file"
  cur_offset=$(($cur_offset + $part_table_offset))
  dd if="$partition_file_1" of="$img_file" bs="$bs" seek="$(($cur_offset/$bs))"
  cur_offset=$(($cur_offset + $partition_size_1))
)

GitHub upstream .

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.