sábado, 27 de junio de 2020

Grabación en Cinta con MT

El comando mt es la forma tradicional en Unix y sistemas similares como Linux o FreeBSD de controlar dispositivos de cinta magnética. Para escribir este artículo voy a utilizar Debian GNU/Linux y una grabadora HP StorageWorks Ultrium 460 que usa cintas LTO-2 y se conecta al ordenador mediante SCSI. Con otros sistemas operativos, grabadoras o tipos de cinta puede haber diferencias.

Los sistemas de archivos en discos o memorias están divididos en directorios y se puede añadir un nuevo archivo en cualquier lugar o acceder casi instantáneamente a cualquier archivo de todo el árbol de directorios usando su nombre. Las cintas son algo mucho más básico, en las cintas se guarda un archivo a continuación de otro, al final de cada archivo se escribe una marca de final de archivo (EOF - End Of File) y al final del último archivo y su marca se añade otra marca que indica el final de los archivos grabados en la cinta y el lugar para escribir el siguiente archivo.

archivo 0 | archivo 1 | archivo 2 || .................

De esta forma es posible detectar donde termina un archivo y comienza otro así como saber cual es el último archivo. Este sistema solo permite añadir archivos al final del último archivo escrito o sobrescribir archivos anteriores y para acceder a un archivo determinado hay que avanzar o retroceder la cinta hasta el lugar donde se encuentra dicho archivo. Además en las cintas generalmente tampoco se guardan metadatos de los archivos como nombre, fecha de creación o tamaño. Solo a partir de la versión 5 de LTO se puede utilizar el sistema de archivos LTFS (Linear Tape File System).

Estas limitaciones de las cintas frente a los discos duros hizo que se dejaran de utilizar para casi todo. Solo permanecieron en algunos casos donde tenían la ventaja de ser un medio de almacenamiento más barato y duradero y/o no se necesitara modificar los datos o acceder rápidamente a un dato determinado. Entre esos casos se encuentran las copias de seguridad, archivo de datos antiguos o grabaciones de video, donde lo importante es almacenar gran cantidad de información con el menor coste posible y con la mayor seguridad de que se podrá recuperar si es necesario. En el caso de las copias de seguridad si todo va bien nunca será necesario recuperar la información.

Para seguir el artículo y practicar las acciones que se indican en él es necesario tener una cinta LTO que no contenga ningún dato que queramos conservar ya que se perderá todo su contenido al escribir desde el inicio de la cinta para simplificar el seguimiento de los resultados. Si se opta por escribir al final de los archivos grabados además de complicar el seguimiento sigue existiendo el peligro de cometer algún error e ir hacía atrás y borrar datos.

En Linux hay dos implementaciones del comando mt: mt-gnu y mt-st. mt-gnu incluye las funciones básicas de toda implementación de mt y mt-st incluye el sistema de inicialización de dispositivos stinit y algunas funciones más para controlar la grabadora. En este artículo se utiliza principalmente mt-st para poder utilizar todas las funciones de la grabadora y se muestran las diferencias con mt-gnu en algunas funciones comunes.

En Debian el comando mt-gnu viene incluido en el paquete cpio y mt-st tiene su propio paquete. En el paquete mtx, que es un software para controlar sistemas automáticos de carga de cintas, se incluye el comando tapeinfo, que permite ver información sobre el lector/grabador de cintas. En el paquete sg3-utils se encuentra el comando sginfo con el que se puede acceder a información de dispositivos SCSI. También se puede ver información sobre la grabadora en los archivos de /sys/class/scsi_tape/. En Debian el comando mt se encuentra en /bin/mt y es un enlace a /etc/alternatives/mt, que a su vez es un enlace a /bin/mt-gnu o /bin/mt-st.

# ls -l /bin/mt

lrwxrwxrwx 1 root root 20 ago 17 23:31 /bin/mt -> /etc/alternatives/mt

# ls -l /etc/alternatives/mt

lrwxrwxrwx 1 root root 10 ago 20 23:27 /etc/alternatives/mt -> /bin/mt-gnu

Con el comando update-alternatives y el parámetro --list se pueden ver las alternativas instaladas para un comando.

# update-alternatives --list mt

/bin/mt-gnu
/bin/mt-st

Para cambiar el comando al que apunta /bin/mt se debe utilizar también el comando update-alternatives. A continuación se muestra como se fija mt-st como destino de /bin/mt. Tanto mt-gnu como mt-st se pueden seguir utilizando usando su nombre completo. En adelante en el artículo, para evitar confusiones, ya que mt-gnu y mt-st tienen funciones diferentes o con nombre ligeramente distinto, se utiliza el nombre completo, pero ya sería posible escribir mt para ejecutar mt-st.

# update-alternatives --set mt /bin/mt-st 

update-alternatives: utilizando /bin/mt-st para proveer /bin/mt (mt) en modo manual

Con el comando lsscsi podemos ver los dispositivos SCSI instalados. Entre ellos aparecerá la grabadora si utiliza este tipo de conexión. El sistema operativo al detectar la grabadora carga el módulo st del kernel, encargado de controlar los dispositivos de cinta SCSI. El comando dmesg permite ver el proceso de inicialización.

# lsscsi

[4:0:0:0]    tape    HP       Ultrium 2-SCSI   F5CD  /dev/st0 


# lsmod | grep st

st                     65536  0
scsi_mod              262144  9 mptsas,st,scsi_transport_sas,aic7xxx,sd_mod,scsi_transport_spi,mptscsih,libata,sg


# dmesg | grep "] st"

[   20.956525] st: Version 20160209, fixed bufsize 32768, s/g segs 256
[   20.957008] st 4:0:0:0: Attached scsi tape st0
[   20.957011] st 4:0:0:0: st0: try direct i/o: yes (alignment 4 B)
[   28.693823] st 4:0:0:0: Attached scsi generic sg1 type 1
[   28.983957] st 4:0:0:0: [st0] Block limits 1 - 16777215 bytes.

Para acceder al lector/grabador se utilizan los dispositivos /dev/st* y /dev/nst*. Al utilizar los dispositivos st la cinta retrocede automáticamente hasta el inicio después de cada acceso y con los nst (no rewind) no retrocede automáticamente. El número que sigue a st y nst indica el número de dispositivo físico. Por cada dispositivo físico en su variante st y nst hay cuatro dispositivos virtuales.

# ls /dev/*st0*

/dev/nst0  /dev/nst0a  /dev/nst0l  /dev/nst0m  /dev/st0  /dev/st0a  /dev/st0l  /dev/st0m

Por defecto se activan los que no tienen letra al final. Los otros seis se pueden activar en el archivo de configuración de stinit (/etc/stinit.def). Para cada par de dispositivos st y nst hay un modo de configuración con el que se le pueden indicar varios parámetros. Este sistema permite tener ocho formas distintas de usar los dispositivos. Más adelante en el artículo se verá como configurar los modos según sea necesario.

mode1 - /dev/st0 y /dev/nst0
mode2 - /dev/st0l y /dev/nst0l
mode3 - /dev/st0m y /dev/nst0m
mode4 - /dev/st0a y /dev/nst0a

Con el parámetro -f se indica al comando mt el dispositivo a utilizar. Con la variable de entorno $TAPE se puede fijar el dispositivo por defecto a usar. De esta forma no es necesario indicarlo cada vez que se ejecute el comando. Desde la consola se puede definir la variable con el comando export.

# export TAPE=/dev/nst0

Para que se asigne para un determinado usuario cuando inicia sesión se puede añadir el comando anterior al archivo .profile del directorio del usuario. Si queremos que se asigne para todos los usuarios se puede añadir la variable al archivo /etc/environment.

TAPE=/dev/nst0

Si ejecutamos los comandos tapeinfo o sginfo indicándoles un dispositivo obtenemos información detallada sobre este.

# tapeinfo -f /dev/nst0

Product Type: Tape Drive
Vendor ID: 'HP      '
Product ID: 'Ultrium 2-SCSI  '
Revision: 'F5CD'
Attached Changer API: No
SerialNumber: 'HUL5K04297'
MinBlock: 1
MaxBlock: 16777215
SCSI ID: 0
SCSI LUN: 0
Ready: yes
BufferedMode: yes
Medium Type: Not Loaded
Density Code: 0x42
BlockSize: 0
DataCompEnabled: yes
DataCompCapable: yes
DataDeCompEnabled: yes
CompType: 0x1
DeCompType: 0x1
BOP: yes
Block Position: 0
Partition 0 Remaining Kbytes: 200448
Partition 0 Size in Kbytes: 200448
ActivePartition: 0
EarlyWarningSize: 0
NumPartitions: 0
MaxPartitions: 0

# sginfo -a /dev/nst0 | more

INQUIRY response (cmd: 0x12)
----------------------------
Device Type                        1
Vendor:                    HP
Product:                   Ultrium 2-SCSI
Revision level:            F5CD

Serial Number 'HUL5K04297'

Read-Write Error Recovery mode page (0x1)
-----------------------------------------
AWRE                               0
ARRE                               0
TB                                 0
RC                                 0
EER                                1
PER                                0
DTE                                0
DCR                                0
Read Retry Count                   21
Correction Span                    0
Head Offset Count                  0
Data Strobe Offset Count           0
Write Retry Count                  10
Recovery Time Limit (ms)           0

Disconnect-Reconnect mode page (0x2)
------------------------------------
Buffer full ratio                  0
Buffer empty ratio                 0
Bus Inactivity Limit (SAS: 100us)  0
Disconnect Time Limit              0
--Más--

Con la acción status del comando mt se puede ver el estado de la cinta y el dispositivo.

# mt-gnu status

drive type = 114
drive status = 1107296256
sense key error = 0
residue count = 0
file number = 0
block number = 0

# mt-st status

SCSI 2 tape drive:
File number=0, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (41010000):
 BOT ONLINE IM_REP_EN

Las dos implementaciones de mt muestran diferentes datos de forma distinta pero ambas muestran los dos parámetros más importantes: File Number y Block Number. File Number nos indica el número de archivo dentro de la cinta y Block Number el número de bloque dentro del archivo. 0 es el primer archivo y en el caso de los bloques 0 es el principio del archivo y -1 el final.

El último archivo en la cinta aún no es un archivo grabado sino solo la posición para grabar el siguiente archivo. Este archivo está vacío y su inicio coincide con el final, el bloque 0 es igual al bloque -1 y su marca de final de archivo y la marca del archivo anterior están juntas indicando el final de los archivos grabados en la cinta.

El comando mt tiene varias acciones para poder avanzar y retroceder en busca de archivos utilizando las marcas de final de archivo, que indican donde termina un archivo y comienza otro. Algunas de estas acciones toman como parámetro el número de marcas a buscar y si no se indica se busca por defecto una sola marca.

  • fsf (Forward Space Files): Avanza las marcas indicadas y avanza al inicio del archivo posterior.
  • bsf (Backward Space Files): Retrocede las marcas indicadas y retrocede al final del archivo anterior.
  • fsfm (Forward Space File Marks): Avanza las marcas indicadas y retrocede al final del archivo anterior.
  • bsfm (Backward Space File Marks): Retrocede las marcas indicadas y avanza al inicio del archivo posterior.
  • eod (End Of Data): Avanza hasta la marca del final de los archivos grabados y lugar para escribir el siguiente archivo. En mt-gnu esta acción recibe el nombre de eom (End Of Media).
  • rewind (Rebobinar) = Retrocede al inicio de la cinta.
  • asf (Absolute Space to File): Retrocede al inicio de la cinta, avanza las marcas indicadas y avanza hasta el inicio del archivo posterior. Si no se indica el número de marcas no busca ninguna y se queda en el inicio de la cinta.

A continuación se muestra una tabla con el archivo y bloque de la cinta después de ejecutar las acciones desde el archivo actual y bloque 0. El carácter | representa una marca de final de archivo.

          Archivo 0 | Archivo 1 (actual) | Archivo 2 (final) |
fsf                                        0
bsf              -1 
fsfm			              -1 
bsfm		      0
eod                                       -1
rewind    0
asf 1                 0

Si indicamos que busque dos marcas el resultado se desplaza un archivo a la derecha para fsf, fsfm y asf, y un archivo a la izquierda para bsf y bsfm.

          A0 | A1 | A2 (actual) | A3 | A4 (final) |
fsf 2                                  0
bsf 2     -1            
fsfm 2                            -1 
bsfm 2         0         
eod                                   -1
rewind    0
asf 2               0

En resumen, viéndolo desde el punto de vista del resultado, sin tener en cuenta el procedimiento usado por el dispositivo, quedaría así:

  • fsf: avanza al principio de los archivos posteriores.
  • bsf: retrocede al final de los archivos anteriores.
  • fsfm: avanza al final del archivo actual o archivos posteriores.
  • bsfm: retrocede al principio del archivo actual o archivos anteriores.
  • eod: avanza al final de la cinta.
  • rewind: retrocede al principio de la cinta.
  • asf: va a un archivo determinado de la cinta.

Viéndolo desde el punto de vista de la posición dentro del archivo las acciones fsf, bsfm, eod y rewind posicionan la cinta al principio del archivo para poder leerlo o escribirlo y las acciones fsfm y bsf la posicionan al final del archivo para poder escribir a continuación.

Para empezar a hacer pruebas la primera acción que vamos a utilizar es rewind para ir al principio de la cinta, así podremos contar los archivos desde 0 y será más sencillo seguir el artículo. Es importante comprobar que la cinta no contiene ningún archivo que queramos conservar ya que quedarán inaccesibles.

Un parámetro importante del estado del dispositivo es Block Size, que indica el tamaño de los bloques en bytes. El tamaño de bloque indica la cantidad de bytes que se pueden leer o escribir en bloque, de una vez. Se puede cambiar y si tiene el valor 0 significa que el tamaño es variable. En el caso de usar mt-gnu, que no muestra este parámetro, se puede visualizar usando tapeinfo.

# tapeinfo -f /dev/nst0 | grep BlockSize

BlockSize: 0

Cuando el tamaño de bloque es variable se puede escribir y leer archivos con cualquier programa sin preocuparnos del tamaño de los datos. Por ejemplo podemos redirigir una cadena de texto con el comando echo, escribir o leer datos con dd, copiar un archivo con el comando cp o leer un archivo con cat de igual forma que lo haríamos con un archivo de un sistema de archivos. Si el tamaño de bloque está fijado en un valor determinado es necesario que la cadena de texto o el archivo a grabar tenga ese mismo tamaño o un múltiplo de este.

Con el comando mt-st se puede fijar el tamaño de bloque utilizando la acción setblk. Si fijamos el tamaño en 32 bytes e intentamos escribir una cadena de texto con echo recibiremos un error si la cadena de texto no tiene el tamaño exacto del bloque o un múltiplo de este.

# mt-st setblk 32
# echo "Prueba Backup 1" > /dev/nst0

-bash: echo: error de escritura: Argumento inválido

Si alargamos la cadena hasta los 32 bytes del tamaño de bloque se grabará correctamente.

# echo "Prueba Backup 1                " > /dev/nst0

Si dos cadenas de texto ocupan menos de 32 bytes se podrían agrupar en un solo bloque y si la cadena ocupa más de 32 bytes habría que usar varios bloques.

El modo automático da más facilidad de uso para grabar datos de tamaño variable pero fijar el tamaño de bloque puede permitir que la velocidad de grabación y lectura sea mayor. Por la mayor complejidad, un tamaño de bloque fijo necesita de algún programa auxiliar que gestione la grabación y lectura de los datos en bloques del tamaño fijado.

En la mayor parte del artículo se utiliza el modo automático para hacer pruebas con diferentes tipos de datos sin importar el tamaño. Para volver a activar el modo automático solo es necesario volver a poner a 0 el tamaño de bloque.

# mt-st setblk 0

Si para algunos programas se necesita tamaño de bloque automático y para otros fijo es posible configurar un modo, por ejemplo mode2, con el tamaño de bloque necesario. Para ello debemos añadir una configuración de dispositivo en el archivo de configuración de stinit (/etc/stinit.def). También se debe indicar el tamaño de bloque de mode1 porque si no tomaría también el tamaño asignado a mode2.

manufacturer="HP" model="Ultrium 2-SCSI" {
    mode1 blocksize=0
    mode2 blocksize=64k
}

Esto nos va a permitir usar los dispositivos /dev/st0l y /dev/nst0l con un tamaño de bloque de 64KiB mientras seguimos utilizando /dev/st0 y /dev/nst0 con tamaño variable.

La información del fabricante y el modelo se puede extraer de la salida de tapeinfo.

# tapeinfo -f /dev/nst0 | grep -e "Vendor ID" -e "Product ID"

Vendor ID: 'HP      '
Product ID: 'Ultrium 2-SCSI  '

Una vez modificada la configuración es necesario ejecutar el comando stinit o reiniciar el equipo para que se apliquen los cambios.

# stinit

Initialized 1 tape device.

Usando el comando mt-st se puede ver el estado de las opciones de la grabadora SCSI en Linux. Estas opciones se aplican a todos los dispositivos virtuales.

# mt-st stshowoptions

The options set: buffer-writes async-writes read-ahead can-bsr

Con el comando mt-st también es posible cambiar las opciones. Es necesario indicar todas las opciones que se quieren activar y omitir las que se quieren desactivar.

# mt-st stsetoptions buffer-writes async-writes read-ahead can-bsr
# mt-st stshowoptions

The options set: buffer-writes async-writes read-ahead can-bsr

En el archivo de configuración de stinit hay algunas de estas opciones para todos los dispositivos.

{buffer-writes read-ahead async-writes}

En la configuración del dispositivo también se pueden activar las opciones.

manufacturer="HP" model="Ultrium 2-SCSI" {
    buffer-writes
    async-writes
    read-ahead
    can-bsr
    mode1 blocksize=0
    mode2 blocksize=64k
}

Si volvemos a ver el estado de la cinta veremos que ahora el número de archivo es 1. La cadena de texto se guardó como archivo 0 y a continuación se escribió automáticamente una marca de final de archivo y otra de final de datos grabados. Ahora la cinta se encuentra en la posición para grabar el archivo 1.

# mt-st status

SCSI 2 tape drive:
File number=1, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Al grabar mas datos se guardará en el archivo 1 y la cinta se quedará en la posición del archivo 2 preparada para grabar el siguiente archivo.

# echo "Prueba Backup 2" > /dev/nst0
# mt-st status

SCSI 2 tape drive:
File number=2, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Si queremos comprobar lo que se ha grabado en el archivo 1 es necesario ir hacía atrás en la cinta. Para ello podemos utilizar la acción bsfm (Backward Space File Marks) para ir al principio del archivo anterior. Si estando en el principio de un archivo ejecutamos la acción bsfm sin indicar el número de marcas buscará la marca anterior y avanzará la cinta hasta el siguiente archivo, por lo que la cinta se quedará en el mismo archivo y bloque. Esto solo sería útil si nos encontráramos al final o en medio del archivo y quisiéramos ir al principio del archivo.

# mt-st bsfm
# mt-st status

SCSI 2 tape drive:
File number=2, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Para leer el archivo 1 debemos indicar que retroceda 2 marcas, la que indica el final del archivo 1 y la que marca el final del archivo 0.

# mt-st bsfm 2
# mt-st status

SCSI 2 tape drive:
File number=1, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Una vez que la cinta está en el bloque 0 del archivo 1 podemos leer el archivo con el comando cat.

# cat /dev/nst0

Prueba Backup 2

Al leer el archivo la cinta avanza por cada uno de los bloques del archivo hasta llegar al siguiente archivo, quedando otra vez en la posición 2. Es importante tener siempre en cuenta que con cada acción de escritura o lectura la cinta avanza y si se quiere volver a leer o escribir en el mismo punto es necesario retroceder la cinta.

# mt-st status

SCSI 2 tape drive:
File number=2, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Si utilizamos el mismo procedimiento para ir al principio del archivo 0 nos dará error de entrada/salida:

# mt-st bsfm 3

/dev/nst0: Input/output error

Esto se debe a que antes del archivo 0, al ser el primer archivo, no hay ninguna marca de final de archivo de un archivo anterior. Aún así se puede comprobar que la cinta ha retrocedido hasta el principio en la búsqueda de las marcas y ha dado el error al llegar al principio de la cinta.

# mt-st status

SCSI 2 tape drive:
File number=0, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (41010000):
 BOT ONLINE IM_REP_EN

Una forma más correcta de ir hasta el principio del primer archivo y que se puede utilizar desde cualquier punto de la cinta es la acción rewind.

# mt-st rewind

Para avanzar en la cinta y volver a la posición 2 se utiliza la acción fsf (Forward Space Files), que avanza hasta el primer bloque de los archivos siguientes. Para volver a la posición 2 debemos decirle que avance dos marcas de final de archivo, las de los archivos 0 y 1.

# mt-st fsf 2
# mt-st status 

SCSI 2 tape drive:
File number=2, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Otras acciones que se pueden utilizar para ir hacia adelante y atrás en la cinta son fsfm (Forward Space File Marks) y bsf (Backward Space Files). Al contrario que los otros comandos estos posicionan la cinta en el último bloque del archivo.

Si desde el archivo 2 ejecutamos bsf 2 retrocederá dos marcas y la cinta se quedará en el final del archivo anterior a la segunda marca, el final del archivo 0. Se puede ver como el número de bloque es -1.

# mt-st bsf 2
# mt-st status 

SCSI 2 tape drive:
File number=0, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

Si desde ahí ejecutamos fsfm 2 buscará las marcas de final de archivo de los archivos 0 y 1 y retrocederá un bloque para quedarse en el final del archivo 1.

# mt-st fsfm 2
# mt-st status 

SCSI 2 tape drive:
File number=1, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

Si se escribe cuando la cinta se encuentra al final de un archivo (bloque -1) los datos se añaden al final del archivo.

# echo "Prueba Backup 3" > /dev/nst0
# mt-st bsfm 2
# cat /dev/nst0

Prueba Backup 2
Prueba Backup 3

Si se escribe cuando la cinta está al principio del archivo este es sobrescrito. De las dos formas se escribe al final una marca de final de archivo y otra de final de datos grabados que hacen que los siguientes archivos en la cinta queden inaccesibles. Donde se escribe pasa a ser el final de los datos en la cinta.

Para poder ir hasta el final de los datos grabados desde cualquier punto de la cinta se puede usar la acción eod (End Of Data). En el caso de mt-gnu la acción es eom (End Of Media).

# mt-st eod
# mt-st status 

SCSI 2 tape drive:
File number=2, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (9010000):
 EOD ONLINE IM_REP_EN

Se puede ver como la cinta se coloca en el archivo 2. El número de bloque es -1, el final de archivo, pero en este caso como el archivo está vacío el bloque -1 es equivalente al bloque 0.

Hay otras dos acciones similares que sirven para avanzar o retroceder bloques dentro de un archivo: fsr (Forward Space Records) y bsr (Backward Space Records). Para probar estos comandos necesitamos grabar algo que tenga un tamaño superior a un bloque, por ejemplo un archivo log.

# cp /var/log/messages /dev/nst0
# mt-st status

SCSI 2 tape drive:
File number=3, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Ahora retrocedemos al principio del archivo y comprobamos que se ha grabado correctamente leyendo su contenido con el comando cat a un archivo temporal.

# mt-st bsfm 2
# cat /dev/nst0 > /tmp/messages.tmp
# vi /tmp/messages.tmp

Aug 17 23:49:51 servidor1 kernel: [    0.000000] Linux version 4.9.0-7-amd64 (debian-kernel@lists.debian.org) (gcc version 6.
3.0 20170516 (Debian 6.3.0-18+deb9u1) ) #1 SMP Debian 4.9.110-3+deb9u2 (2018-08-13)
Aug 17 23:49:51 servidor1 kernel: [    0.000000] Command line: BOOT_IMAGE=/boot/vmlinuz-4.9.0-7-amd64 root=/dev/sda1 ro quiet
Aug 17 23:49:51 servidor1 kernel: [    0.000000] x86/fpu: Legacy x87 FPU detected.
...

Una vez comprobado volvemos al principio del archivo y utilizamos la acción fsr para avanzar un bloque. Se puede ver como el número de bloque es 1.

# mt-st bsfm 2
# mt-st fsr
# mt-st status

SCSI 2 tape drive:
File number=2, block number=1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

Si ahora leemos la cinta ya no empezará a leer desde el principio del archivo sino a partir del bloque 1.

# cat /dev/nst0 > /tmp/messages.tmp
# vi /tmp/messages.tmp

: [    0.148979] pci 0000:01:00.0: PCI bridge to [bus 02]
Aug 18 14:08:45 servidor1 kernel: [    0.149052] pci 0000:00:1c.0: PCI bridge to [bus 07]
Aug 18 14:08:45 servidor1 kernel: [    0.149391] pci 0000:0d:00.0: disabling ASPM on pre-1.1 PCIe device.  You can enable it 
with 'pcie_aspm=force'
...

Si en algún momento se quiere volver atrás algunos bloques se puede utilizar la acción bsr, a la que se le puede pasar como parámetro el número de bloques. En el siguiente ejemplo se vuelve al principio del archivo, se avanza dos bloques con fsr y se retroceden dos bloques con bsr.

# mt-st bsfm 2
# mt-st fsr 2
# mt-st status

SCSI 2 tape drive:
File number=2, block number=2, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

# mt-st bsr 2
# mt-st status

SCSI 2 tape drive:
File number=2, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Hay que tener en cuenta que si se parte del final del archivo (bloque -1) el número de bloque seguirá marcando -1 aunque se haya retrocedido algún bloque. Cuando se parte de un determinado número de bloque el dispositivo puede ir restando una unidad a ese número pero cuando se parte del final, como el dispositivo no conoce el número de bloques del archivo, no tiene un número de referencia del que ir restando.

# mt-st fsfm
# mt-st status

SCSI 2 tape drive:
File number=2, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

# mt-st bsr
# mt-st status

SCSI 2 tape drive:
File number=2, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

Otra forma de posicionar la cinta en un determinado archivo es utilizar la acción asf (Absolute Space to File) que retrocede hasta el principio de la cinta y avanza el número de marcas que se le indica.

# mt-st asf 1
# mt-st status

SCSI 2 tape drive:
File number=1, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 EOF ONLINE IM_REP_EN

Manejar una gran cantidad de archivos usando solo los comandos mt y cp sería muy complejo. Para grabar varios archivos se utiliza el comando tar. Este comando recibe su nombre de "Tape Archiving", ya que fue creado originalmente para grabar archivos en cintas. En la actualidad es común su uso en cualquier situación que requiera agrupar varios archivos. Para usarlo con la cinta solo hay que utilizar el dispositivo de cinta como parámetro -f (file). Por ejemplo podemos ir al final de la cinta (archivo 3) y guardar los archivos del directorio /usr/bin comprimidos con bzip2 (parámetro -j).

# mt-st eod
# tar cjf /dev/nst0 /usr/bin

Si volvemos atrás al principio del archivo guardado y utilizamos el parámetro -t del comando tar podemos leer la lista de archivos contenidos en el archivo tar. Con el parámetro -v se muestran los detalles del archivo. Con el comando tar, aunque la cinta no tenga sistema de archivos, podemos grabar y leer trozos o sistemas de archivos enteros.

# mt-st bsfm 2
# tar tvjf /dev/nst0 | more

drwxr-xr-x root/root         0 2020-06-16 01:08 usr/bin/
-rwxr-xr-x root/root     56168 2017-02-22 13:23 usr/bin/sha224sum
lrwxrwxrwx root/root         0 2018-08-17 23:31 usr/bin/from -> /etc/alternatives/from
-rwxr-xr-x root/root      3562 2020-01-25 18:54 usr/bin/ptar
lrwxrwxrwx root/root         0 2017-12-28 10:47 usr/bin/infotocap -> tic
-rwxr-xr-x root/root      3172 2015-06-05 00:55 usr/bin/file-rename
...

Si vamos otra vez al principio del archivo y utilizamos el parámetro -x podemos extraer el contenido. Con el parámetro -C se indica el directorio de destino.

Si se ha cancelado el listado antes de llegar al siguiente archivo el número de bloque será uno intermedio del archivo y para volver al principio habrá que usar bsfm sin ningún parámetro para que solo retroceda una marca.

# mt-st status

SCSI 2 tape drive:
File number=3, block number=557, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (1010000):
 ONLINE IM_REP_EN

# mt-st bsfm
# tar xjf /dev/nst0 -C /root

Si ha llegado hasta el archivo 4 habrá que usar bsfm 2.

# mt-st status

SCSI 2 tape drive:
File number=4, block number=0, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (81010000):
 ONLINE IM_REP_EN

# mt-st bsfm 2
# tar xjf /dev/nst0 -C /root

También se puede copiar a un archivo del sistema de archivos y abrirlo después.

# mt-st bsfm 2
# cp /dev/nst0 usr-bin.tar
# tar xjf usr-bin.tar

Si solo se necesita extraer un solo archivo o directorio se le puede indicar al comando tar. En el siguiente ejemplo se extrae el archivo usr/bin/lscpu. Es necesario indicar la ruta completa según aparece en el listado de archivos obtenido con el parámetro -t. Esta ruta también se utiliza como ruta relativa para guardar el archivo en el directorio destino.

# mt-st bsfm 2
# tar xjf /dev/nst0 -C /root usr/bin/lscpu
# ls -l /root/usr/bin/lscpu 

-rwxr-xr-x 1 root root 64712 mar  7  2018 /root/usr/bin/lscpu

El comando tar además nos permite indicar el tamaño de bloque y por tanto puede ser utilizado para grabar en la cinta cuando el tamaño de bloque está fijado en un valor determinado. Si intentamos escribir en el dispositivo /dev/nst0l que tiene fijado el tamaño de bloque en 64 KiB recibiremos el mismo error que cuando intentábamos escribir una cadena de texto de tamaño menor al bloque.

# tar cjf /dev/nst0l /usr/bin

tar: Eliminando la `/' inicial de los nombres
tar (child): /dev/nst0l: No se puede efectuar write: Argumento inválido
tar (child): Error is not recoverable: exiting now
tar: /dev/nst0l: Sólo se escribieron 6144 de 10240 bytes
tar: Child returned status 2
tar: Error is not recoverable: exiting now

Pero si indicamos el tamaño de bloque la grabación se realizará correctamente. Se debe indicar como número de bloques de 512 bytes ya que el comando tar escribe en bloques de este tamaño. Por lo tanto es necesario que el tamaño de bloque fijado en el grabador de cintas sea un múltiplo de 512. Partiendo de un tamaño de bloque de la grabadora de 64 KiB (65536 bytes), se divide entre 512 bytes por bloque de tar y el resultado es 128 bloques (65536 bytes / 512 bytes = 128 bloques).

# tar cjf /dev/nst0l /usr/bin -b 128

Para poder leer lo escrito es necesario leerlo en bloques del mismo tamaño en el dispositivo configurado para ello.

# mt-st bsfm 2
# tar xjf /dev/nst0l -C /root -b 128

El comando dd también permite indicar el tamaño de bloque. Si no se indica daría el siguiente error:

# dd if=/usr/bin/perl of=/dev/nst0l

dd: escribiendo en '/dev/nst0l': Argumento inválido
1+0 registros leídos
0+0 registros escritos
0 bytes copied, 0,000425097 s, 0,0 kB/s

Indicando el tamaño de bloque de 64 KiB se graba correctamente. Es necesario añadir el parámetro conv=sync para que al final del archivo se rellene con ceros lo que falte hasta completar el último bloque de 64KiB. A leer el archivo sería necesario eliminar estos ceros.

# dd if=/usr/bin/perl of=/dev/nst0l bs=64k conv=sync

30+1 registros leídos
31+0 registros escritos
2031616 bytes (2,0 MB, 1,9 MiB) copied, 1,73044 s, 1,2 MB/s

Cuando la cinta esté llena y se quiera reutilizar o se quieran eliminar los datos se puede usar la acción erase para borrar toda la cinta. Esto puede tardar mucho tiempo, una forma mucho más rápida de reutilizar la cinta es simplemente volver a escribir desde el principio o un punto intermedio, recordemos que se fija el final de los datos grabados después de la última grabación realizada.

También se puede utilizar la acción eof para fijar el final de archivo y de cinta en cualquier parte de un archivo. Por ejemplo podemos fijar el final de archivo y cinta en el bloque 2 del archivo 2.

# mt-st asf 2
# mt-st fsr 2
# mt-st eof

Acto seguido podemos comprobar que el final de la cinta se encuentra en la posición 3 y los archivos que hemos grabado ya no están accesibles.

# mt-st eod
# mt-st status

SCSI 2 tape drive:
File number=3, block number=-1, partition=0.
Tape block size 65536 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (9010000):
 EOD ONLINE IM_REP_EN

Otro parámetro importante que se puede fijar con mt-st es la compresión por hardware, que con datos no comprimidos puede llegar hasta una relación de compresión de 2 o 2,5 a 1, doblando la capacidad de la cinta. Si los datos que se guardan ya están comprimidos la compresión por hardware no va a reducir el tamaño que ocupen e incluso lo puede aumentar. Los dispositivos modernos son inteligentes y cuando el tamaño comprimido es mayor se guardan los datos sin comprimir.

El comando mt-st tiene dos acciones distintas para activar o desactivar la compresión: defcompression y compression. defcompresion fija la compresión por defecto para uno de los dispositivos virtuales y compression fija la compresión para el dispositivo físico y tiene preferencia sobre defcompression.

La compresión por defecto solo se usa en circunstancias muy determinadas como cuando se cambia de cinta o de dispositivo virtual y se escribe desde el principio, por lo que tiene un uso limitado y puede causar confusión. Si por ejemplo hemos escrito con un dispositivo virtual con compresión y después queremos escribir a continuación con otro dispositivo virtual sin compresión no se aplicará la compresión por defecto y tendremos que desactivarlo con la acción compression. Es más sencillo utilizar scripts que activen o desactiven la compresión según sea necesario.

Para activar la compresión se le pasa al comando mt-st con la acción compression el valor 1 y para desactivarla el 0. El estado de la compresión en el dispositivo se puede ver con el comando tapeinfo. Tanto para mt-st como tapeinfo se puede usar cualquiera de los dispositivos virtuales ya que la acción se realiza en el dispositivo físico.

# mt-st -f /dev/nst0 compression 1
# tapeinfo -f /dev/nst0 | grep DataCompEnabled

DataCompEnabled: yes

Otra forma de ver el estado de la compresión en el dispositivo físico es usar el comando sginfo. El parámetro DCE es Data Compression Enabled (Compresión de Datos Habilitada).

# sginfo -a /dev/nst0 -t 0xf

INQUIRY response (cmd: 0x12)
----------------------------
Device Type                        1
Vendor:                    HP
Product:                   Ultrium 2-SCSI
Revision level:            F5CD

Serial Number 'HUL5K04297'

Data compression mode page (0xf)
----------------------------------------------------
DCE                                1
DCC                                1
DDE                                1
RED                                0
Compression algorithm              1
Decompression algorithm            1

Las grabadoras de cinta suelen tener la capacidad de leer las cintas de versiones anteriores. Si tenemos una grabadora LTO-2 seguramente pueda leer cintas LT0-1 e incluso escribir en ellas. Es posible que la grabadora detecte automáticamente la tecnología de la cinta o puede ser necesario indicárselo. Esto no he podido probarlo porque no tengo cintas LTO-1.

Cada una de las tecnologías de cinta tiene un código llamado Density Code (Código de Densidad). Con la acción densities podemos ver un listado de códigos de diferentes tecnologías de cinta.

# mt-st densities

Some SCSI tape density codes:
code   explanation                   code   explanation
0x00   default                       0x33   SLR6
0x01   NRZI (800 bpi)                0x34   SLR100
0x02   PE (1600 bpi)                 0x40   DLT1 40 GB, or Ultrium
0x03   GCR (6250 bpi)                0x41   DLT 40GB, or Ultrium2
0x04   QIC-11                        0x42   LTO-2
0x05   QIC-45/60 (GCR, 8000 bpi)     0x44   LTO-3
0x06   PE (3200 bpi)                 0x45   QIC-3095-MC (TR-4)
0x07   IMFM (6400 bpi)               0x46   LTO-4
0x08   GCR (8000 bpi)                0x47   DDS-5 or TR-5
0x09   GCR (37871 bpi)               0x48   SDLT220
0x0a   MFM (6667 bpi)                0x49   SDLT320
0x0b   PE (1600 bpi)                 0x4a   SDLT600, T10000A
0x0c   GCR (12960 bpi)               0x4b   T10000B
0x0d   GCR (25380 bpi)               0x4c   T10000C
0x0f   QIC-120 (GCR 10000 bpi)       0x4d   T10000D
0x10   QIC-150/250 (GCR 10000 bpi)   0x51   IBM 3592 J1A
0x11   QIC-320/525 (GCR 16000 bpi)   0x52   IBM 3592 E05
0x12   QIC-1350 (RLL 51667 bpi)      0x53   IBM 3592 E06
0x13   DDS (61000 bpi)               0x54   IBM 3592 E07
0x14   EXB-8200 (RLL 43245 bpi)      0x55   IBM 3592 E08
0x15   EXB-8500 or QIC-1000          0x58   LTO-5
0x16   MFM 10000 bpi                 0x5a   LTO-6
0x17   MFM 42500 bpi                 0x5c   LTO-7
0x18   TZ86                          0x71   IBM 3592 J1A, encrypted
0x19   DLT 10GB                      0x72   IBM 3592 E05, encrypted
0x1a   DLT 20GB                      0x73   IBM 3592 E06, encrypted
0x1b   DLT 35GB                      0x74   IBM 3592 E07, encrypted
0x1c   QIC-385M                      0x75   IBM 3592 E08, encrypted
0x1d   QIC-410M                      0x80   DLT 15GB uncomp. or Ecrix
0x1e   QIC-1000C                     0x81   DLT 15GB compressed
0x1f   QIC-2100C                     0x82   DLT 20GB uncompressed
0x20   QIC-6GB                       0x83   DLT 20GB compressed
0x21   QIC-20GB                      0x84   DLT 35GB uncompressed
0x22   QIC-2GB                       0x85   DLT 35GB compressed
0x23   QIC-875                       0x86   DLT1 40 GB uncompressed
0x24   DDS-2                         0x87   DLT1 40 GB compressed
0x25   DDS-3                         0x88   DLT 40GB uncompressed
0x26   DDS-4 or QIC-4GB              0x89   DLT 40GB compressed
0x27   Exabyte Mammoth               0x8c   EXB-8505 compressed
0x28   Exabyte Mammoth-2             0x90   SDLT110 uncompr/EXB-8205 compr
0x29   QIC-3080MC                    0x91   SDLT110 compressed
0x30   AIT-1 or MLR3                 0x92   SDLT160 uncompressed
0x31   AIT-2                         0x93   SDLT160 comprssed
0x32   AIT-3 or SLR7

Si vemos el estado de un dispositivo podremos ver el código de densidad de la cinta. En mi caso 0x42 (LTO-2).

# mt-st status

SCSI 2 tape drive:
File number=3, block number=-1, partition=0.
Tape block size 0 bytes. Density code 0x42 (LTO-2).
Soft error count since last status=0
General status bits on (9010000):
 EOD ONLINE IM_REP_EN

Al leer o escribir cintas de la versión anterior, si la grabadora no detecta automáticamente la tecnología de la cinta, será necesario configurarla con el código de densidad 0x40 (DLT1 40 GB, or Ultrium). Para ello se puede usar el comando mt-st con la acción setdensity y cualquiera de los dispositivos activos.

# mt-st -f /dev/nst0 setdensity 0x40

También en el archivo de configuración de stinit podemos añadir el parámetro density con el código a uno de los modos ya activados o podemos activar otro modo y sus dispositivos asociados.

manufacturer="HP" model="Ultrium 2-SCSI" {
    buffer-writes
    async-writes
    read-ahead
    can-bsr
    mode1 blocksize=0 
    mode2 blocksize=64k
    mode3 density=0x40
}

Una vez que hayamos terminado con el uso de la cinta se puede rebobinar y expulsar con la acción offline.

# mt-st offline

Con los comandos mt-st, tar y algún script que mantenga un registro de los archivos tar grabados y automatice la grabación y recuperación de datos ya se pueden hacer sistemas de copias de seguridad muy completos y adaptados a las necesidades de cada sistema. También se puede optar por usar sistemas de copia de seguridad ya creados como Amanda o Bacula. Se use un sistema u otro siempre es útil conocer el funcionamiento básico del lector/grabador de cintas y comandos como mt-st, tapeinfo y sginfo para la resolución de problemas y la comprobación de que todo funciona bien.

No hay comentarios:

Publicar un comentario