miércoles, 21 de febrero de 2007

[Backup] Sincronizar dos carpetas con rsync (1ª parte)


 Los "backup" son una serie de artículos, mensajes y posts que he ido escribiendo a lo largo de los años en las webs y blogs que he tenido y que estoy tratando de agrupar y recuperar para "la posteridad" en este blog.

Antecedentes "históricos":

Ya estuve hablando hace un tiempo del programa unison y cómo sincronizar carpetas con él según mi necesidad: pendrive - ordenador, ordenador – pendrive. Pues bien: me he enfadado con unison. Resulta que como por arte de magia las carpetas del pez (el pendrive) han pasado a estar en minúsculas, y se ve que el unison es sensible a las mayus y minus pero sólo en una de las direcciones (creo que en dirección hacia el pez), por lo que se empeña en decirme que tengo carpetas nuevas cuando en realidad tengo las mismas carpetas de siempre. La única diferencia es que él las ve como con las capitalizaciones cambiadas y las da por nuevas.

No puedo demostrarlo (o no sé hacerlo), pero creo que la culpa de todo la tiene que cuando hago el “unisonado” (toma palabro) en casa lo hago “pez-linux, linux-pez” y cuando lo he hecho en la universidad ha sido “pez-windoz, windoz-pez”. Basándome en la molesta configuración que traen los windoz de la universidad (las extensiones de archivo “más comunes” ocultas, los archivos ocultos permanecen invisibles, etc... ya sabéis de que hablo ;-) ), seguro que tienen activa alguna opción de estas del tipo “mostrar todos los nombres de carpeta en mayúsculas independientemente del nombre original” (ahora mismo no cito textualmente pero opciones de este tipo he visto yo por ahí por “Herramientas > opciones de carpeta > nosequé”...)

El caso es que como me he enfadado con él, y como encima para “unisonear” en la universidad me tenía que meter en windoz, tocar cada vez el path (como ya expliqué en su momento) y todo el rollo, me he tenido que buscar alternativas más... digamos “flexibles”. Tan flexibles como mirar si los linux de la universidad tienen algún paquete de sincronización de archivos y aprender a usarlo. Tan flexibles como: $ apt-cache search sync

Ver el (único) resultado que se adaptaba a mis necesidades: rsync - A program for synchronizing files over a network Y decirme a mí mismo: Vale, pues toca aprender a usar rsync... :-p

Ahora sí, al grano:

Googleando un poquito podemos encontrar:

Según la definición de rsync de la wikipedia en español "Rsync es una aplicación para sistemas de tipo Unix que ofrece transmisión eficiente de datos incrementales comprimidos y cifrados. Mediante una técnica de delta encoding, permite sincronizar archivos y directorios entre dos máquinas de una red o entre dos ubicaciones en una misma máquina, minimizando el volumen de datos transferidos.

Vale, parece que vamos por buen camino. Esta es la página web oficial (creo) de rsync. Podemos hacer una búsqueda sobre rsync en el formulario googlero de las listas de usuarios de debian, y encontraremos unos cuantos muchos resultados con hilos que hablan sobre el programita en cuestión. Pero yo, personalmente, he encontrado mucha información al respecto, pero ninguna útil para mi propósito...

¿Siguiente paso? Pues googlear el tema, por supuesto: PUES NO!! al menos no si todavía no he publicado esto (porque espero que me encontréis cuando lo publique y busquéis sobre esto :-p ), porque lo que os encontraréis (al menos según mi experiencia) son montones y montones de resultados que hablan de sincronizar carpetas remotas, una carpeta local con una remota, un servidor remoto con una carpeta local, bla bla bla... pero nada que nos explique “cómo sincronizar una carpeta de la memoria usb con una del pc de sobremesa (o del portátil)”. O simplemente “cómo usar rsync localmente”, que viene a ser lo mismo.

¿Desesperado? Pues sí, pero todavía me quedan dos opciones: buscar respuestas en la web oficial de rsync o leer el man del programita. Lo malo es que las dos opciones pasan por ponerse a leer en inglés. Pero como, aparte de un poco cansado, para mí no es problema... pues qué le vamos a hacer.

La página de rsync, en su sección de ejemplos, ofrece ejemplos sólo referidos al uso en sincronización de servidores, por lo que no nos sirve.

El man de rsync más de lo mismo, pero podemos sacar información útil para nuestro caso...
-a : no sé bien de que va esta opción, pero creo que le dice a rsync que trate con archivos.
-r : le dice que haga el sincronizado recursivamente (o sea: recorriendo todos los subdirectorios del directorio especificado)
-v : “verbose”. Creo que sirve para que se muestre en pantalla lo que va haciendo el rsync.
-z : no sé si para el caso es útil pero creo que lo que hacer es transmitir los datos comprimidos, supongo que por ahorrar tiempo y ancho de banda.



Pruebas:

1.- creo un directorio “origen” y un directorio “destino”. Creo varios archivos:
$ ls > ./origen/listado.txt; ls -l > ./origen/listado_detallado.txt; ls Desktop > ./destino/lista_Desktop.txt

Como veis he creado dos en el directorio origen y uno en destino, para ver el efecto de rsync sobre los archivos ya creados en destino y que no existen en origen.

El primer $ rsync -a ./origen/* ./destino/*

no surte efecto porque sobra el asterisco de destino. $ rsync -a ./origen/* ./destino/

funciona pero como me salto el “-v” no sé lo que ha hecho rsync hasta que no listo el contenido de los directorios. Pero vamos, que lo que hace es copiar los dos archivos de origen al directorio destino.

Ahora toca ver si actualiza los archivos: $ ls -l >> ./origen/listado_detallado.txt // para incrementar el contenido del archivo
$ rsync -av ./origen/* ./destino/ // repetimos pero con la -v para ver lo que hace

Y lo hace sin problemas. Si devolvemos el archivo a su estado original (es decir, la mitad de lo que es ahora), podremos observar que sigue actualizando correctamente. Omito los pasos porque es reutilizar pasos anteriores.

Ahora nos gustaría comprobar si cuando borramos un archivo en origen se borra en destino. Lo natural sería hacer: $ rm ./origen/listado.txt // para borrar el archivo listado.txt
$ rsync -av ./origen/* ./destino/

Sin embargo nos vamos a topar con que el archivo no se borra :-(

Después de investigar el fenómeno me he dado cuenta de que fallan dos cosas: la primera que hay que añadir la opción “--delete” para que borre los archivos que en origen no están y en destino sí. Y la segunda que hay que quitar el asterisco de origen para que nos haga caso el comando. Lo del asterisco no tengo muy claro porqué pero está explicado en el man del programa.

La cuestión es que la línea quedaría: $ rsync -av --delete ./origen/ ./destino/

Y ahora sí se borraría el archivo que sobra.

Vale, pues nada, ya tenemos más o menos cogido el puntito a la sicronización (o eso esperamos...). Ahora hay que subir un nivel: sincronizar contando con la existencia de subdirectorios. Lo primero será creárselos, claro:
mkdir ./origen/subori1;
mkdir ./origen/subori2;
mkdir ./destino/subdes1;
mkdir ./destino/subdes2;

Una vez más, contamos con contenido exclusivo de destino para ver qué tal se porta con él rsync... Y creamos archivos para esos subdirectorios:
ls > ./origen/listado.txt;
ls Desktop > ./destino/lsDesktop.txt;
ls origen > origen/subori1/lsorigen.txt;
ls origen > origen/subori1/lsorigen2.txt;
ls origen >> origen/subori1/lsorigen2.txt;
ls origen > origen/subori2/lsorigen.txt;
ls origen > origen/subori2/lsorigen2.txt;
ls origen >> origen/subori2/lsorigen2.txt;
ls destino > destino/subdes1/lsdestino.txt;
ls destino > destino/subdes1/lsdestino2.txt;
ls destino >> destino/subdes1/lsdestino2.txt;
ls destino > destino/subdes2/lsdestino.txt;
ls destino > destino/subdes2/lsdestino2.txt;
ls destino >> destino/subdes2/lsdestino2.txt

Esto crea de nuevo los archivos listado.txt y lsDesktop.txt, y un par de archivos en cada uno de los cuatro subdirectorios que hemos creado. Puede parecer un poco mareante crearse tantos archivos de golpe pero podemos observar con la ayuda de ls origen/*;
ls destino/*

que lo que hemos hecho está bien hecho ;-)

Ahora a la faena:

Primero ver si sincronizan los subdirectorios: rsync -av ./origen/ ./destino/

Todo se actualiza correctamente. Ahora eliminamos uno de los subdirectorios que acabamos de copiar en destino. Y también creamos un sub subdirectorio en el subdirectorio subori2 y un archivo en él. Esto lo hacemos por darle un nivel de “complejidad” más al árbol de directorios: mkdir origen/subori2/subsubori;
ls -lh > origen/subori2/subsubori/listado_humano.txt;
rm destino/subori1/*;
rmdir destino/subori1

Sincronizamos... rsync -avz origen/ destino/ Y todo bien. Ahora la prueba final: eliminar un subdirectorio de origen para que se elimine en destino: rm origen/subori1/*;
rmdir origen/subori1;
rsync -avz –delete origen/ destino/
Muy bien: nos acabamos de cargar el subori1, pero también los originales de destino subdes1 y subdes2 :-) Ala, mira qué bien!!

Resumiendo:

Hasta aquí lo que hemos aprendido es a que el origen y el destino tengan exactamente el mismo contenido. Esto incluye modificaciones de archivo de origen a destino, y también la eliminación de cualquier archivo que exista en destino pero no exista en origen. Es decir: origen manda. Y destino es un espejo de origen.

Cuando usábamos unison teníamos algo parecido, pero con la ventaja de poder elegir qué hacer con cada cambio detectado (ignorarlo, copiar hacia el “origen” o copiar hacia el “destino”). Todavía no hemos llegado a ese nivel con rsync, pero seguro que lo alcanzaremos ;-)