Linux: ¿cómo formatear múltiples sistemas de archivos dentro de un archivo?

9

Necesito crear una imagen de disco con dos sistemas de archivos vacíos. Lo he creado usando

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

A continuación, he creado 2 particiones primarias usando fdisk disk.img; uno es FAT32 y otro es EXT3. Ahora, tengo que formatear ambas particiones para crear sistemas de archivos para montar como -o loop devices. ¿Pero no puedo entender cómo formatearlos? No puedo usar mkfs.vfatel disk.img. Entonces estoy totalmente confundido.

SOLUCIÓN: Gracias a la respuesta de @ pjc50 encontré una solución muy 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 inconveniente de esta solución es el requisito de derechos de superusuario.

psihodelia
fuente
Dudo que todos esos programas puedan usar particiones dentro de un archivo. ¿Puede crear los dos sistemas de archivos en archivos separados y luego combinarlos en un archivo grande con dd?
golimar
@golimar: pero necesitaré MBR en esa unidad, no sé cómo es posible fusionar diferentes sistemas de archivos creados por separado como archivos distintos
psihodelia 12/12/11
Puede usar el MBR del archivo original que dijo. dd permite compensaciones con los comandos 'tamaño' y 'omitir'. Necesitaría encontrar los desplazamientos exactos y luego sobrescribir parte del archivo grande con los dos más pequeños
golimar
Perdóname si estoy siendo ingenuo aquí, pero ¿por qué no usar solo dos archivos separados?
Garrett

Respuestas:

9

Parece que puede usar las herramientas de kpartx: http://robert.penz.name/73/kpartx-a-tool-for-mounting-partitions-within-an-image-file/

Kpartx se puede usar para configurar asignaciones de dispositivos para las particiones de cualquier dispositivo de bloque particionado. Es parte de las herramientas de múltiples rutas de Linux. Con kpartx -l imagefile obtienes una visión general de las particiones en el archivo de imagen y con kpartx -a imagefile las particiones serán accesibles a través de / dev / mapper / loop0pX (X es el número de la partición). Puede montarlo ahora con mount / dev / mapper / loop0pX / mnt / -o loop, ro. Después de desmontar, puede desconectar los dispositivos del mapeador con kpartx -d imagefile.
pjc50
fuente
Sin embargo, un inconveniente de esta solución es el requisito de derechos de superusuario.
psihodelia
1
¡Dudo que exista una solución que no requiera derechos de superusuario! Es decir, este es el tipo de operación que no espero que los usuarios normales puedan hacer sin un mecanismo específico configurado por adelantado por el súper usuario (por ejemplo, a través de sudo)
pjc50
2
@ pjc50: es posible hacer esto sin derechos de superusuario: primero se debe crear cada partición como un archivo separado, luego crear manualmente la imagen del disco y copiar las particiones en la imagen del disco después de crear la tabla de particiones en la imagen del disco.
Mikko Rantalainen
1
@MikkoRantalainen exactamente. Aquí es un ejemplo ejecutable mínima: superuser.com/a/1367534/128124
Ciro Santilli冠状病毒审查六四事件法轮功
7

Puede hacerlo montando primero sus particiones para /dev/loop?usarlas losetupcon la -oopción de especificar un desplazamiento adecuado para su partición. El desplazamiento se puede calcular en función de la salida de fdisk -l disk.img( start_sector * sector_size).

Por ejemplo:

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

Una vez montado, puede proceder a formatear la partición usando mkfs.*:

mkfs.vfat -F32 /dev/loop1

Para obtener más detalles y ejemplos, consulte los siguientes artículos:

Shawn Chin
fuente
Bueno, no funciona :(
psihodelia
@psihodelia Debería. ¿Cuál es el resultado si haces esto?
Daniel Beck
¿Cómo no funciona? ¿Le da un error? ¿Qué paso falla?
Shawn Chin
$ sudo mkfs.vfat -F32 / dev / loop1 mkfs.vfat 3.0.9 (31 de enero de 2010) El dispositivo de bucle no coincide con un tamaño de disquete, usando los parámetros de hd predeterminados
psihodelia
1
Podría ayudar si especifica el tamaño del bloque al llamar mkfs.vfat. Ver primer enlace que proporcioné. También mencionado en el artículo, la advertencia de disquete se espera y se puede ignorar
Shawn Chin
1

Iría con las herramientas que tengo en mente:

  • crear una nueva máquina virtual en Virtualbox con un disco, que normalmente sería /dev/sda
  • iniciar en la VM con un CD en vivo GParted
  • particione y formatee el disco en la VM según sus necesidades (2 particiones, diferentes sistemas de archivos, etc.)
  • luego use ddpara exportar /dev/sdaa un archivo

Con una suposición educada, tomaría unos 15 minutos.

karatedog
fuente
Solución inteligente y complicada :) Pero no creo que tarde menos de 15 minutos. Por cierto, es difícil automatizarlo, ya que requiere un usuario en una interfaz gráfica (por lo tanto, no es posible la secuencia de comandos = no es un modo Unix).
psihodelia
No lleva mucho tiempo :-) porque el disco virtual es pequeño y no se realiza la instalación del sistema operativo. La parte más larga es el tiempo de arranque GParted.
karatedog
1

Ejecutable mínimo sfdisk+ mke2fsejemplo sinsudo

En este ejemplo, crearemos, sin sudoo setsuid, un archivo de imagen que contenga dos particiones ext2, cada una de ellas con archivos de un directorio de host.

Luego usaremos sudo losetupsolo para montar las particiones para probar que el kernel de Linux realmente puede leerlas como se explica en: /programming/1419489/how-to-mount-one-partition-from-an-image -archivo-que-contiene-particiones múltiples / 39675265 # 39675265

Para más detalles, ver:

El ejemplo:

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

Probado en Ubuntu 18.04. GitHub aguas arriba .

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