viernes, 27 de mayo de 2016

tar

En el mundo del software tipo Unix, el programa tar es la herramienta clásica para empaquetar. Su nombre, abreviatura de tape archive, revela sus raíces como una herramienta para hacer copias de seguridad en cinta. Aunque aún se usa para su tarea tradicional, está igualmente adaptada en otros dispositivos de almacenamiento.

A menudo vemos nombres de archivo que terminan con la extensión .tar o .tgz, que indican un paquete tar "plano" y un paquete comprimido con gzip, respectivamente. Un paquete tar puede consistir en un grupo de archivos separados, una o más jerarquías de directorios, o una mezcla de ambas. La sintaxis del comando funciona así:

tar modo[opciones] ruta...

donde modo es uno de los siguientes modos de operación (sólo se muestra una lista parcial; mira la man page de tar para ver la lista completa):

Tabla 18-2: Modos de tar
Modo Descripción
c Crea un paquete de una lista de archivos y/o directorios.
x Extrae un archivo.
r Añade rutas específicas al final de un archivo.
t Lista el contenido de un paquete.

tar usa una forma un poco extraña para expresar las opciones, así que necesitaremos algunos ejemplos para mostrar como funciona. Primero, recreemos nuestro patio de juegos del capítulo anterior:

[me@linuxbox ~]$ mkdir -p playground/dir-{001..100}
[me@linuxbox ~]$ touch playground/dir-{001..100}/file-{A..Z}

A continuación, creemos un paquete tar del patio de juegos completo:

[me@linuxbox ~]$ tar cf playground.tar playground

Este comando crea un paquete tar llamado playground.tar que contiene la jerarquía completa del directorio playground. Podemos ver que el modo y la opción f, que hemos usado para especificar el nombre del paquete tar, pueden ir juntas, y no requieren un guión delante. Fíjate, sin embargo, que el modo siempre debe ser especificado primero, antes que ninguna opción.

Para listar los contenidos del paquete, podemos hacer ésto:

[me@linuxbox ~]$ tar tf playground.tar

Para un listado más detallado, podemos añadir la opción v (verbose):

[me@linuxbox ~]$ tar tvf playground.tar

Ahora, extraigamos el patio de juegos en una nueva localización. Lo haremos creando un nuevo directorio llamado foo, cambiando el directorio y extrayendo el paquete tar:

[me@linuxbox ~]$ mkdir foo
[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground.tar
[me@linuxbox foo]$ ls
playground

Si examinamos el contenido de ~/foo/playground, vemos que el paquete ha sido instalado exitosamente, creando un reproducción precisa de los archivos originales. Sin embargo, hay una advertencia: A menos que estés operando como superusuario, los archivos y los directorios extraídos de paquetes toman la propiedad del usuario que realiza la restauración, en lugar del propietario original.

Otro comportamiento interesante de tar es la forma en que maneja las rutas en los archivos. Por defecto son relativas, en lugar de absolutas. tar hace ésto simplemente eliminando cualquier barra al principio de las rutas cuando creamos el archivo. Para demostralo, volvemos a crear nuestro paquete, esta vez especificando una ruta absoluta:

[me@linuxbox foo]$ cd
[me@linuxbox ~]$ tar cf playground2.tar ~/playground

Recuerda, ~/playground se expandirá en /home/me/playground cuando pulsemos la tecla intro, así tendremos una ruta absoluta para nuestra demostración. A continuación, extraeremos el paquete como antes y veremos que ocurre:

[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar
[me@linuxbox foo]$ ls
home playground
[me@linuxbox foo]$ ls home
me
[me@linuxbox foo]$ ls home/me
playground

Aquí podemos ver que cuando extrajimos nuestro segundo paquete, volvió a crear el directorio home/me/playground relativo a nuestro directorio de trabajo actual, ~/foo, no relativo al directorio root, como hubiese sido con rutas absolutas. Esto podría parecer una forma extraña de trabajar, pero en realidad es más útil de esta manera, ya que nos permite extraer paquetes en cualquier sitio en lugar de ser forzados a extraerlos en sus localizaciones originales. Repitiendo el ejercicio con la inclusión de la opción verbose (v) nos dará una imagen más clara de lo que está pasando.

Consideremos un ejemplo hipotético, aunque práctico, de tar en acción. Imagina que queremos copiar el directorio home y su contenido de un sistema a otro y tenemos un gran disco duro USB que usaremos para la transferencia. En nuestro sistema Linux moderno, la unidad se monta "automágicamente" en el directorio /media. Imaginemos también que el disco tiene nombre de volumen BigDisk cuando lo conectamos. Para crear el paquete tar, podemos hacer lo siguiente:

[me@linuxbox ~]$ sudo tar cf /media/BigDisk/home.tar /home

Después de que se escriba el paquete tar, desmontamos el disco y lo conectamos al segundo ordenador. De nuevo, se monta en /media/BigDisk. Para extraer el paquete, hacemos lo siguiente:

[me@linuxbox2 ~]$ cd /
[me@linuxbox2 /]$ sudo tar xf /media/BigDisk/home.tar

Lo que es importante ver aquí es que primero tenemos que cambiar el directorio a /, para que la extracción sea relativa al directorio root, ya que todas las rutas dentro del paquete son relativas.

Cuando extraemos un paquete, es posible limitar qué se extrae de él. Por ejemplo, si queremos extraer un archivo individual de un paquete, podría hacerse así:

tar xf paquete.tar ruta

Añadiendo la ruta al final del comando, tar sólo restaurará el archivo especificado. Pueden especificarse múltiples rutas. Fíjate que la ruta deber ser exactamente igual a la ruta almacenada en el paquete. Cuando especificamos rutas, los comodines generalmente no están soportados; sin embargo, la versión GNU de tar (que es la versión que encontramos más a menudo en las distribuciones Linux) los admite con la opción --wildcards. Aquí tenemos un ejemplo usando nuestro paquete playground.tar anterior:

[me@linuxbox ~]$ cd foo
[me@linuxbox foo]$ tar xf ../playground2.tar --wildcards 'home/me/playground/dir-*/file-A'

Este comando extraerá sólo los archivos que coincidan con la ruta especificada incluyendo el comodín dir-*.

tar se usa a menudo junto con find para producir paquetes. En este ejemplo, usaremos find para producir un conjunto de archivos e incluirlos en un paquete:

[me@linuxbox ~]$ find playground -name 'file-A' -exec tar rf playground.tar '{}' '+'

Aquí usamos find para buscar todos los archivos de playground llamados file-A y luego, usando la acción -exec, invocamos a tar en el modo inclusión (r) para añadir los archivos buscados al paquete playground.tar.

Usar tar con find es una buena forma de crear copias de seguridad incrementales de un árbol de directorios o de un sistema completo. Usando find para buscar archivos más nuevos que un archivo con una marca de tiempo, podríamos crear una paquete que sólo contenga archivos más nuevos que el último archivo, asumiendo que el archivo con la marca de tiempo se ha actualizado justo después de que se cree cada paquete.

tar puede también usar tanto entrada estándar como salida estándar. Aquí hay un ejemplo detallado:

[me@linuxbox foo]$ cd
[me@linuxbox ~]$ find playground -name 'file-A' | tar cf - --files-from=- | gzip > playground.tgz

En este ejemplo, usamos el programa find para producir una lista de archivos coincidentes y canalizamos a través de tar. Si se especifica el nombre de archivo "-", toma el significado de entrada o salida estándar, según sea necesario (Por cierto, este acuerdo de usar "-" para representar entrada/salida estándar se usa también en muchos otros programas). La opción --files-from (que también puede especificarse como -T) hace que tar lea su lista de rutas de un archivo en lugar de la línea de comandos. Finalmente, el paquete producido por tar es canalizado a gzip para crear el paquete comprimido playground.tgz. La extensión .tgz es la extensión convencional dada a los paquetes tar comprimidos con gzip. A veces, también se usa la extensión .tar.gz.

Aunque hemos usado el programa gzip externamente para producir nuestro paquete comprimido, las versiones modernas de GNU tar soportan tanto compresión gzip como bzip2 directamente, con el uso de las opciones z y j, respectivamente. Usando nuestro ejemplo anterior como base, podemos simplificarlo de esta forma:

[me@linuxbox ~]$ find playground -name 'file-A' | tar czf
playground.tgz -T -

Si hubiéramos querido crear un paquete bzip2 comprimido, podríamos haber hecho esto:

[me@linuxbox ~]$ find playground -name 'file-A' | tar cjf playground.tbz -T -

Simplemente cambiando la opción de compresión de z a j (y cambiando la extensión del archivo de salida a .tbz para indicar que es un archivo comprimido con bzip2) habilitamos la compresión bzip2.

Otro uso interesante de la entrada y salida estándar con el comando tar implica transferir archivos entre sistemas a través de una red. Imagina que tenemos dos máquinas ejecutando un sistema tipo Unix equipadas con tar y ssh. En tal escenario, podríamos transferir un directorio de un sistema remoto (llamado remote-sys para este ejemplo) a nuestro sistema local:

[me@linuxbox ~]$ mkdir remote-stuff
[me@linuxbox ~]$ cd remote-stuff
[me@linuxbox remote-stuff]$ ssh remote-sys 'tar cf - Documents' | tar xf -
me@remote-sys’s password:
[me@linuxbox remote-stuff]$ ls
Documents

Así podríamos copiar un directorio llamado Documents de un sistema remoto remote-sys a un directorio incluido en el directorio llamado remote-stuff en el sistema local. ¿Cómo hacemos ésto? Primero, ejecutamos el programa tar en el sistema remoto usando ssh. Recordarás que ssh nos permite ejecutar un programa remotamente en un ordenador conectado a una red y "ver" el resultado en el sistema local: la salida estándar producida en el sistema remoto se envía al sistema local para visualizarla. Podemos aprovechar esto haciendo que tar cree un paquete (el modo c) y lo envíe a la salida estándar, en lugar de a un archivo (la opción f con el guión como argumento), de esta forma transportamos el archivo a través de un túnel encriptado proporcionado por ssh en el sistema local. En el sistema local, ejecutamos tar y hacemos expandir un paquete (el modo x) suministrado desde la entrada estándar (de nuevo con la opción f con el guión como argumento).

No hay comentarios:

Publicar un comentario