Linux - comment formater plusieurs systèmes de fichiers dans un seul fichier?

9

J'ai besoin de créer une image disque avec deux systèmes de fichiers vides. Je l'ai créé en utilisant

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

Ensuite, j'ai créé 2 partitions principales en utilisant fdisk disk.img; l'un est FAT32 et l'autre est EXT3. Maintenant, je dois formater les deux partitions afin de créer des systèmes de fichiers à monter en tant que -o loop devices. Mais je ne comprends pas comment les formater? Je ne peux pas utiliser mkfs.vfatsur disk.img. Je suis donc totalement confus.

SOLUTION: Grâce à la réponse de @ pjc50, j'ai trouvé une solution très simple:

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

Un inconvénient de cette solution est l'exigence de droits de superutilisateur.

psihodelia
la source
Je doute que tous ces programmes pourront utiliser des partitions à l'intérieur d'un fichier. Pouvez-vous créer les deux systèmes de fichiers dans des fichiers séparés, puis les fusionner dans un gros fichier avec dd?
golimar
@golimar: mais j'aurai besoin de MBR sur un tel lecteur, je ne sais pas comment il est possible de fusionner différents systèmes de fichiers créés séparément en tant que fichiers distincts
psihodelia
Vous pouvez utiliser le MBR du fichier d'origine que vous avez dit. dd autorise les décalages avec les commandes 'size' et 'skip'. Vous auriez besoin de trouver les décalages exacts, puis d'écraser une partie du gros fichier avec les deux plus petits
Golimar
Pardonnez-moi si je suis naïf ici, mais pourquoi ne pas simplement utiliser deux fichiers distincts?
Garrett

Réponses:

9

Il semble que vous pouvez utiliser les outils kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

Kpartx peut être utilisé pour configurer les mappages de périphériques pour les partitions de tout périphérique de bloc partitionné. Il fait partie des outils multivoie Linux. Avec kpartx -l fichier image, vous obtenez un aperçu des partitions dans le fichier image et avec kpartx -a fichier image, les partitions seront accessibles via / dev / mapper / loop0pX (X est le numéro de la partition). Vous pouvez le monter maintenant avec la boucle mount / dev / mapper / loop0pX / mnt / -o, ro. Après le démontage, vous pouvez déconnecter les périphériques du mappeur avec le fichier image kpartx -d.
pjc50
la source
Cependant, un inconvénient de cette solution est l'exigence de droits de superutilisateur.
psihodelia
1
Je doute qu'il existe une solution qui ne nécessite pas de droits de superutilisateur! Autrement dit, c'est le genre d'opération que je ne m'attends pas à ce que les utilisateurs normaux puissent se passer d'un mécanisme spécifique mis en place par le super utilisateur à l'avance (par exemple via sudo)
pjc50
2
@ pjc50: il est possible de le faire sans droits de superutilisateur: il faut d'abord créer chaque partition dans un fichier séparé, puis créer manuellement l'image disque et copier les partitions sur l'image disque après avoir créé la table de partition sur l'image disque.
Mikko Rantalainen
1
@MikkoRantalainen exactement. Voici un exemple exécutable minimal: superuser.com/a/1367534/128124
Ciro Santilli 法轮功 病毒 审查 六四 事件 法轮功
7

Vous pouvez le faire en montant d'abord vos partitions à l' /dev/loop?aide losetupde l' -ooption permettant de spécifier un décalage approprié pour votre partition. Le décalage peut être calculé sur la base de la sortie de fdisk -l disk.img( start_sector * sector_size).

Par exemple:

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

Une fois monté, vous pouvez ensuite procéder au formatage de la partition en utilisant mkfs.*:

mkfs.vfat -F32 /dev/loop1

Pour plus de détails et d'exemples, consultez les articles suivants:

Shawn Chin
la source
Eh bien, cela ne fonctionne pas :(
psihodelia
@psihodelia Ça devrait. Quel est le résultat si vous faites cela?
Daniel Beck
Comment ça ne marche pas? Vous obtenez une erreur? Quelle étape échoue?
Shawn Chin
$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 janvier 2010) Le périphérique de boucle ne correspond pas à une taille de disquette, en utilisant les paramètres hd par défaut
psihodelia
1
Peut aider si vous spécifiez la taille du bloc lors de l'appel mkfs.vfat. Voir le premier lien que j'ai fourni. Également mentionné dans l'article, l'avertissement de disquette est attendu et peut être ignoré
Shawn Chin
1

J'irais avec les outils que j'ai en tête:

  • créer une nouvelle machine virtuelle dans Virtualbox avec un disque, ce serait généralement /dev/sda
  • démarrer dans la machine virtuelle avec un CD Live GParted
  • partitionnez et formatez le disque dans la VM selon vos besoins (2 partitions, différents systèmes de fichiers, etc.)
  • puis utiliser ddpour exporter /dev/sdavers un fichier

Avec une supposition éclairée, cela prendrait environ 15 minutes.

karatedog
la source
Solution délicate et intelligente :) Mais je ne pense pas que cela prenne moins de 15 minutes. Soit dit en passant, il est difficile de l'automatiser, car il nécessite un utilisateur dans une interface graphique (donc, aucun script n'est possible = pas une manière Unix).
psihodelia
Cela ne prend pas longtemps :-) car le disque virtuel est petit et aucune installation de système d'exploitation n'est effectuée. La partie la plus longue est le temps de démarrage GParted.
karatedog
1

Exécution minimale sfdisk+ mke2fsexemple sanssudo

Dans cet exemple, nous allons créer, sans sudoou setsuid, un fichier image contenant deux partitions ext2, chacune remplie de fichiers provenant d'un répertoire hôte.

Nous utiliserons ensuite sudo losetupjuste pour monter les partitions pour tester que le noyau Linux peut réellement les lire comme expliqué sur: /programming/1419489/how-to-mount-one-partition-from-an-image -file-that-contains-multiple-partitions / 39675265 # 39675265

Pour plus de détails, voir:

L'exemple:

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

Testé sur Ubuntu 18.04. GitHub en amont .

Ciro Santilli 冠状 病毒 审查 六四 事件 法轮功
la source