Come formattare una partizione all'interno di un file img?


12

Ho creato un imgfile tramite il seguente comando:

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

È solo un file con zero, ma posso usarlo fdiske creare una tabella delle partizioni:

# 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, diciamo, una partizione:

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 controllo la tabella delle partizioni, ottengo il seguente risultato:

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

Quindi la partizione esiste. Quando provo a formattare questa partizione tramite gparted, ottengo il seguente errore:

inserisci qui la descrizione dell'immagine

Non so perché lo cerchi binary.img1, e non ho idea di come formattare la partizione dal comando live.

Qualcuno sa come formattarlo usando il filesystem ext4?


2
Un'opzione è fare il trucco losetup da questa risposta e quindi eseguire mkfs.ext4 contro il dispositivo di loopback.
Miikka,

Ho trovato questo link unix.stackexchange.com/a/87189/52763 . E questo è in realtà quello che volevo. Il problema è che quando controllo il dispositivo in gparted, ottengo Couldn't find valid filesystem superblock.. Ecco la foto: i.imgur.com/dl7XAC4.png . È una specie di bug?
Mikhail Morfikov,

Risposte:


13

È possibile accedere all'immagine del disco e alle sue singole partizioni tramite la funzione di loopback. Hai già scoperto che alcune utilità del disco funzioneranno (ragionevolmente) felicemente sulle immagini del disco. Tuttavia, mkfsnon è uno di questi (ma stranamente lo mountè).

Ecco l'output di 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

Per accedere alla partizione che hai creato hai un paio di scelte

  1. Il percorso esplicito

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

    L'output /dev/loop0è il nome del dispositivo loop che è stato allocato. Il --offsetparametro è solo l'offset della partizione ( Start) moltiplicato per la dimensione del settore ( 512). Considerando che --sizelimitè la dimensione della partizione, e puoi calcolarla nel modo seguente: End-Start + 1, che è 819199-2048 + 1 = 817152, e anche quel numero deve essere moltiplicato per la dimensione del settore.

    È quindi possibile utilizzare /dev/loop0come riferimento alla partizione:

    mkfs -t ext4 -L img1 /dev/loop0
    mkdir -p /mnt/img1
    mount /dev/loop0 /mnt/img1
    ...
    umount /mnt/img1
    losetup -d /dev/loop0
    
  2. La via implicita

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

    L'output /dev/loop0è il nome del dispositivo ad anello primario che è stato allocato. Inoltre, l' --partscanopzione dice al kernel di scansionare il dispositivo alla ricerca di una tabella delle partizioni e assegnare automaticamente i dispositivi ad anello sussidiario. Nel tuo caso con una partizione si ottiene anche /dev/loop0p1, che è quindi possibile utilizzare come riferimento alla partizione:

    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 di vederti calcolato la dimensione della partizione quando era già stata data come parte fdiskdell'output.
roaima,

2
Cosa c'è di sbagliato in alcuni calcoli? Inoltre, è bello sapere che puoi ottenere facilmente il giusto numero di settore in quel modo, nel caso in cui ...
Mikhail Morfikov

Solo una breve osservazione: "il frontend di mkfs è deprecato a favore di mkfs specifici per filesystem. <type> utils", citato dalle pagine man di mkfs.
gmagno,

@gmagno ora è corretto, certamente. Ma per quanto posso determinare senza scavare troppo a lungo o troppo a fondo, quell'avviso è stato rilasciato solo per la prima volta con util-linux 2.25-rc1 e non è entrato in Debian stable fino a qualche tempo dopo giugno 2015. Sentiti libero per aggiornare la risposta con le informazioni attuali però.
roaima,

11

C'è un altro modo per farlo in generale, usare kpartx( non correlato a kde)

sudo kpartx -a binary.img

e ora dovresti avere tutti i dispositivi di partizione definiti /dev/mappercome loop0p1 , loop0p2 , ...

e poi

sudo mkfs.ext4 /dev/mapper/loop0p1

Opzionalmente, quando hai finito, puoi anche correre

sudo kpartx -d binary.img

sbarazzarsi del loop0p? deivce


2
Non sono sicuro del perché questo non abbia più voti. IMO è la migliore risposta ...!
Jeremy Davis,

Funziona con le partizioni GPT, ad esempio, se si desidera modificare la partizione EFI da un intero disco dd.
Russ,

3

Non so perché lo cerchi binary.img1

(... e più tardi per binary.img2sepolto nel commento.)

Questo perché gli strumenti si aspettano che i nomi dei file seguano uno schema specifico. Tale modello è quello utilizzato dai file del dispositivo per dischi effettivi e volumi di dischi sul sistema, vale a dire:

  • Un file di dispositivo che comprende l'intero disco viene chiamato sda(o qualcos'altro). Questo è ciò che si fdiskaspetta di sfruttare.
  • File di dispositivo per i singoli slice del disco, descritto dal suo partizionamento, sono denominati sda1, sda2, sda3e così via. Questo è ciò che strumenti come si gpartedaspettano di fare quando dicono mkfsdi fare cose sui singoli volumi del disco .

Naturalmente, i file ordinari non si sovrappongono come fanno i file dei dispositivi del disco. Le discussioni che coinvolgono il filesystem di loopback che avete visto sono tutti di prendere un singolo file immagine dell'intero disco e l'utilizzo di loopback per creare i 1, 2, 3file, e così via che riflettono le singole sezioni all'interno di esso, una volta che il layout della partizione desiderata è stata scritta alla tabella delle partizioni.


Ciò ha senso!
Mikhail Morfikov,

0

Sebbene questo argomento non sia direttamente correlato, menziona molte delle stesse informazioni e correlate.

Wiki Debian | Raspberry Pi e qemu-user-static

Se non è possibile utilizzare aptper installare alcuni dei comandi menzionati in questo post, provare a utilizzare apt-cache search [package_name]. Ciò non può generare alcun risultato se il comando proviene da un pacchetto con un nome diverso.

Ad esempio, in losetupprecedenza poteva essere installato come losetupusando apt install losetup, ma ora fa parte del util-linuxrepository di Ubuntu. Per scoprire quale pacchetto funge da contenitore per un altro pacchetto, è necessario utilizzare la ricerca del repository online per la propria distribuzione Linux. Oppure, se è necessario installarlo da un'altra fonte, utilizzare un motore di ricerca Web.

Vale la pena dare un'occhiata ad alcuni pacchetti ...

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

Ogni distribuzione Linux ha anche le sue manpage online. A volte è più facile usare le manpage che un tutorial. Le pagine del manuale ti diranno anche tutte le opzioni e i parametri di comando. Un tutorial di solito si concentrerà solo su quelli utilizzati.


0

Eseguibile minimo sfdisk+ mke2fsesempio senzasudo

In questo esempio, creeremo, senza sudoo setsuid, un file di immagine che contiene due partizioni ext2, ciascuna popolata con file da una directory host.

Useremo quindi sudo losetupsolo per montare le partizioni per verificare che il kernel Linux possa effettivamente leggerle come spiegato su: /programming/1419489/how-to-mount-one-partition-from-an-image -file-che-contiene-multiple-partizioni / 39.675.265 # 39675265

Per maggiori dettagli, vedi:

L'esempio:

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

Testato su Ubuntu 18.04. GitHub a monte .

Aiuto per avvolgere un file filesystem grezzo esistente in un'immagine

Estratto da quanto sopra, può essere utile quanto segue:

# 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 a monte .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.