Usar un fichero como un Disco

Linux Nivel Alto 22 de ago. de 2024

En Linux todo son ficheros

Si recordáis, en artículos anteriores ya hemos comentado que Linux, todo son ficheros y se tratan como tales: Los dispositivos son ficheros, los directorios son ficheros y los ficheros son ficheros...

Usando ficheros como discos

Dado que todo son ficheros, puede que un determinado momento necesitemos disponer de un "disco" extra para realizar alguna tarea sobre él o simplemente practicar comandos de particionado o de formateo.

Creando un fichero

Para transformar un fichero en un dispositivo (o disco), lo primero que deberemos hacer es crearlo del tamaño que vayamos a necesitar.

Vamos a usar el comando dd que nos permite crear un fichero del tamaño deseado de una forma muy sencilla.

La sintaxis para usar dd es la siguiente:

dd if=dispositivo-entrada of=dispositivo-salida [opciones]

Como dispositivo de entrada vamos a usar /dev/zero para generar caracteres nulos con los que "rellenar el fichero".

Como dispositivo de salida vamos a indicar el nombre de un fichero en el que escribiremos.

En la parte de opciones indicaremos como parametro el tamaño de bloque (bs o block-size) que deseamos usar y además cuantas veces vamos iterar para generar multiples bloques mediante el parámetro count

Vamos a crear nuestro primer fichero disco de un tamaño aproximado de 200 Mb:

# Generar fichero vacio de 200 Mb en una única escritura
dd if=/dev/zero of=disco bs=200M count=1
1+0 records in
1+0 records out
209715200 bytes (210 MB, 200 MiB) copied, 0,146605 s, 1,4 GB/s

Obtenemos el siguiente resultado en pantalla:

Formateando el fichero

Ahora simplemente podemos formatear el fichero para que se comporte como un sistema de ficheros y poderlo montar y usarlo como si fuese un disco, necesitamos privilegios de root para realizarlo:

# Formatear como ext4 el fichero
sudo mkfs.ext4 disco 

En la pantalla veremos:

Compramos que tipo de fichero es mediante el comando file:

file disco 

disco: Linux rev 1.0 ext4 filesystem data, 
       UUID=47a317b3-0455-473b-a770-9ad740abe910 
       (extents) (64bit) (large files) (huge files)

Montando el fichero como si fuese un disco

Para poderlo usar simplemente necesitaremos crear un punto de montaje y como usuario root montar nuestro nuevo dispositivo (fichero):

# Crear punto de montaje (pruebas en /tmp):
mkdir -p /tmp/punto-montaje

# Montar fichero (disco):
sudo mount disco /tmp/punto-montaje/ 

Podemos comprobar si está montado correctamente, y el tamaño del disco:


# Comprobamos si esta montado...
mount|grep -i disco
  /tmp/disco on /tmp/punto-montaje type ext4 (rw,relatime)
  
# Comprobar tamaño del "disco"
df -h /tmp/punto-montaje/

S.ficheros     Tamaño Usados  Disp Uso% Montado en
/dev/loop0       182M    14K  168M   1% /tmp/punto-montaje

Podemos observar que tanto el tamaño del disco, como el espacio disponible no se corresponde con el total de tamaño del fichero.

Esto se debe a que al formatear el dispositivo con el File System deseado, hay cierto espacio que se reserva para gestionar la tabla de particiones, el journaling, etc.

Podemos acceder al disco, cambiandonos simplemente al punto de montaje y usarlo como si fuese un dispositivo normal.

cd /tmp/punto-montaje/

ls -l
total 12
drwx------ 2 root root 12288 ago 22 01:34 lost+found

Una vez usado, para desmontarlo simplemente escribiremos:

sudo umount /tmp/punto-montaje

Fichero como disco con Particiones

Ahora vamos a ver algo un poco más avanzado. Vamos a crear un fichero, crear particiones dentro de él, formatear cada partición y montarlas.

Creación del fichero

El procedimiento es identico y usaremos el comando dd tal y como hicimos anteriormente:

# Creamos fichero de tamaño aprox de 220 Mb
dd if=/dev/zero of=disco-particion bs=220M count=1

1+0 records in
1+0 records out
230686720 bytes (231 MB, 220 MiB) copied, 0,0999712 s, 2,3 GB/s

Particionado del fichero

Podemos usar el comando fdisk (como root)  para crear las particiones que deseemos en el fichero disco-particion que hemos creado.

En nuestro caso para simplificar unicamente voy a crear 2 particiones:

sudo fdisk disco-particion 

Y vamos contestando a cada una de las preguntas:

Bienvenido a fdisk (util-linux 2.38.1).
Los cambios solo permanecerán en la memoria, hasta que decida escribirlos.
Tenga cuidado antes de utilizar la orden de escritura.

El dispositivo no contiene una tabla de particiones reconocida.
Created a new DOS (MBR) disklabel with disk identifier 0xe3693333.

Orden (m para obtener ayuda): n
Tipo de partición
   p   primaria (0 primaria(s), 0 extendida(s), 4 libre(s))
   e   extendida (contenedor para particiones lógicas)
Seleccionar (valor predeterminado p): p
Número de partición (1-4, valor predeterminado 1): 1
Primer sector (2048-450559, valor predeterminado 2048): 
Último sector, +/-sectores o +/-tamaño{K,M,G,T,P} (2048-450559, valor predeterminado 450559): +110M

Crea una nueva partición 1 de tipo 'Linux' y de tamaño 110 MiB.

Orden (m para obtener ayuda): n
Tipo de partición
   p   primaria (1 primaria(s), 0 extendida(s), 3 libre(s))
   e   extendida (contenedor para particiones lógicas)
Seleccionar (valor predeterminado p): p
Número de partición (2-4, valor predeterminado 2): 2
Primer sector (227328-450559, valor predeterminado 227328): 
Último sector, +/-sectores o +/-tamaño{K,M,G,T,P} (227328-450559, valor predeterminado 450559): 

Crea una nueva partición 2 de tipo 'Linux' y de tamaño 109 MiB.

Orden (m para obtener ayuda): w

Se ha modificado la tabla de particiones.
Se están sincronizando los discos.

Comprobar particiones
Para comprobar si se han creado las particiones usaremos de nuevo el comando dd con el parámetro --list:

sudo fdisk -l disco-particion 
Disco disco-particion: 220 MiB, 230686720 bytes, 450560 sectores
Unidades: sectores de 1 * 512 = 512 bytes
Tamaño de sector (lógico/físico): 512 bytes / 512 bytes
Tamaño de E/S (mínimo/óptimo): 512 bytes / 512 bytes
Tipo de etiqueta de disco: dos
Identificador del disco: 0xe3693333

Disposit.        Inicio Comienzo  Final Sectores Tamaño Id Tipo
disco-particion1            2048 227327   225280   110M 83 Linux
disco-particion2          227328 450559   223232   109M 83 Linux

Otra forma de verlo sería mediante el comando file:

file disco-particion 

disco-particion: DOS/MBR boot sector; 
partition 1 : ID=0x83, start-CHS (0x0,32,33), end-CHS (0xe,38,24),
              startsector 2048, 225280 sectors; 
partition 2 : ID=0x83, start-CHS (0xe,38,25), end-CHS (0x1c,11,47),
              startsector 227328, 223232 sectors

Calculando el Offset de las Particiones del Fichero

Si intentas acceder a las particiones de fichero, verás que no puedes realizar ninguna operación con ellas.
Para poder gestionarlas, hay que usar el valor de offset (desplazamiento) para indicar a los comandos necesarios (formate o montaje) a que posición tiene que acceder para realizar la operación indicada.

Paso 1. Obtener el valor del tamaño del sector
Aunque por defecto el valor suele ser de 512 bytes, es recomendable comprobarlo.
Si observas el resultado del comando fdisk -l disco-particion verás que el valor se mostraba en la línea:
Tamaño de sector (lógico/físico): 512 bytes / 512 bytes

Paso 2. Obtener el offset de inicio de cada partición
Debemos fijarnos en que sector se inicia cada partición:

La 1ª particion disco-particion1 comienza en el sector 2048
La 2ª partición disco-particion2 comienza en el sector 227328

Para calcular el offset simplemente se multiplica el tamaño de sector por el sector de inicio de cada partición.

Podemos hacer la operación desde la propia terminal sin necesidad de usar una calculadora:

# Calcular offset de disco-particion1 (sector 2048):
echo $((2048 * 512))
1048576

# Calcular offset de disco-particion2 (sector 227328):
echo $((227328 * 512))
116391936

Formatear las Particiones del Fichero

Con los valores de offset calculados ya puedes formatear cada una de sus particiones.
Al comando mkfs deberás indicarle como dispositivo el nombre del fichero y como parámetro extra el offset calculado anteriormente:
-E offset=ValorOFFSET:

# Formatear la 1ª particion (como ext4)
sudo mkfs.ext4 disco-particion -E offset=1048576

# Formatear la 2ª particion (como ext4)
sudo mkfs.ext4 disco-particion -E offset=116391936

Montar las Particiones del Fichero

Al igual que con el formateo, para realizar el montaje de cada partición podemos usar el comando mount, pero indicaremos la posición de inicio en la que buscar el sistema de ficheros, mediante el parámetro -o le indicaremos el offset:


# Montar 1ª partición:
sudo mount -o offset=1048576 disco-particion /tmp/montaje-part1/

# Montar 2ª partición:
sudo mount -o offset=116391936 disco-particion /tmp/montaje-part2/

Mediante un montaje directo con mount al intentar montar la 2ª partición nos encontraremos con el error:
mount: ya existe un dispositivo de bucle que solapa con disco-particion.

Para poder montar varias veces el mismo fichero usaremos el comando losetup y también usaremos los valores de los offset obtenidos.

# losetup 1ª particion (en loop-1)
sudo losetup /dev/loop1 --offset 1048576 disco-particion 
# losetup 2ª particion (en loop-2)
sudo losetup /dev/loop2 --offset 116391936 disco-particion


# Montar loopN en punto de montaje:
 2282  sudo mount /dev/loop1 /tmp/montaje-part1/
 2283  sudo mount /dev/loop2 /tmp/montaje-part2/

Si comprobamos el montaje y tamaño disponible:

df -h

S.ficheros     Tamaño Usados  Disp Uso% Montado en
...
/dev/loop1       200M   2,8M  182M   2% /tmp/montaje-part1
/dev/loop2        97M    14K   90M   1% /tmp/montaje-part2

Script para calcular offset

Si quieres simplificar aun más cálculo del offset, te dejo un script sencillo para que puedas obtener las particiones y los valores de desplazamiento de cada partición para cualquier dispositivo:

Para su uso debes usarlo como usuario root o mediante sudo.
Si lo ejecutas sin ningún parámetro te mostrará la ayuda de uso:

sudo ./offset-fileImage.sh

--------------------------------------------------------------
USAGE 1:
  ./offset-fileImage.sh file-image.img
  Return the list of all existing partitions of the file-image
--------------------------------------------------------------
USAGE 2:
  ./offset-fileImage.sh file-image.img NUMBER
  Returns the offset number of the file-image partitions
  to format or mount it.
--------------------------------------------------------------

Etiquetas

Luis GuLo

🐧 SysAdmin GNU/Linux - 🐳 Docker - 🖥️ Bash Scripting - 🐪 Perl - 🐬 MySQL - 👥 Formador de TI - 👥 Formador de SysAdmin's - 💢 Ansible - ☁️ Cloud Computing - ❤️ Debian GNU/Linux