20 de Julio, 2006

Mejorando mi estrategia de copias de seguridad con rsync

Hay mucha documentación sobre cómo realizar copias de seguridad empleando rsync, así que he estado leyendo un rato para evitar esos 'casi' que me encontré el otro día cuando tuve que recuperar un backup.

La idea es hacer copias de seguridad incrementales bajo demanda, o de forma automatizada, de mi estación de trabajo con Ubuntu en mi servidor con OpenBSD, guardando una historia de las últimas n copias, y además haciéndolo de forma rápida y sin consumir demasiado disco. Parece un objetivo ambicioso, a ver qué sale :).

Para ello he seguido instrucciones de Mike Rubel: Easy Automated Snapshot-Style Backups with Linux and Rsync. Lo que me ha parecido interesante del texto de Rubel es que usa enlaces fuertes para ficheros repetidos sin cambios entre copias consecutivas, de forma que el consumo de disco es más razonable (actualmente mi copia de seguridad es de 772 MB).

Los enlaces simbólicos es una característica que tienen todos los sistemas de archivos de sistemas tipo UNIX que se basan en nodos. Simplificando mucho consiste en que varios nombres de fichero apunten a los mismos datos. Hay dos tipos de enlaces básicamente: enlaces fuertes y enlaces débiles. En este caso nos interesa emplear enlaces fuertes porque llevan una cuenta de las referencias a los datos, es decir, cuántos nombres apuntan a mismo trozo de disco. Así los datos no desaparecen hasta que la última referencia se elimina, permitiéndonos ahorrar disco al trabajar con el mismo fichero situado en directorios distintos (lo que supone una referencia distinta).

En primer lugar hay que permitir que el servidor donde se van a realizar las copias de seguridad pueda acceder a la estación de trabajo sin contraseña, empleando claves RSA sin contraseña.

Para ello ejecutamos en el servidor lo siguiente, suponiendo user_s como el usuario del servidor que hace los backups:

$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/user_s/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/user_s/.ssh/id_rsa.
Your public key has been saved in /home/user_s/.ssh/id_rsa.pub.
The key fingerprint is:
91:7e:ec:01:a2:e2:f5:d7:87:f6:2c:f7:38:87:71:04 user_s@blackshell.usebox.net

Es importante no introducir contraseña. Copiamos la clave pública a la estación de trabajo y eliminamos el original en el servidor, suponiendo user_w como el usuario en la estación de trabajo:

$ scp /home/user_s/.ssh/id_rsa.pub user@192.168.0.1:/home/user_w
$ rm /home/user_s/.ssh/id_rsa.pub

Ahora en la estación de trabajo añadimos la clave pública a las claves autorizadas para entrar en la cuenta de nuestro usuario:

$ cat id_rsa.pub >> /home/user_w/.ssh/authorized_keys
$ rm id_rsa.pub

Con estos pasos ya podemos crear procesos automatizados en el servidor que conecten vía SSH a la estación de trabajo sin que se les pida contraseña, lo cual es razonable porque no pueden introducirla ;).

Ahora solo hay que programar un sencillo script en el servidor para que realice una rotación de los directorios donde están las copias de seguridad (la copia más vieja se borra y en su lugar se pone la anterior, sobre la anterior la anterior, y así hasta que la primera queda vacía para la nueva copia), y ejecute rsync adecuadamente.

El script que propongo es el siguiente:

#!/bin/sh

# número de rotaciones
COUNT=3
# nombre base para las copias
BASE=bak
# directorio de trabajo
WORK=/var/backup_estacion

cd $WORK

i=$COUNT
rm -rf $BASE.$i

while [ $i -gt 0 ]; do

        mv $BASE.$(($i-1)) $BASE.$i 2> /dev/null
        mv $BASE.$(($i-1))-info $BASE.$i-info 2>/dev/null

        i=$(($i-1))
done

echo "Rotated on `date`" > $BASE.0-info

# ahora hacemos rsync con algo como:
rsync -avz --delete -e ssh --link-dest=../$BASE.1 \
user_w@IP_ESTACION:/home/user_w/Desktop/Documentos/ $BASE.0/

# EOF

En este caso hago copia del directorio Documentos de mi escritorio, que es donde guardo la información de una forma ordenada, y es lo que me interesa guardar en la copia de seguridad. En realidad hago otra llamada a rsync para copiar el correo, pero prefiero simplificar el ejemplo.

Ahora, para realizar un backup bajo demanda, solo tengo que guardar este script como backup.sh con permisos de ejecución en el servidor y llamarlo desde la estación de trabajo con algo como:

$ ssh user_s@IP_SERVIDOR /home/user_s/bin/backup.sh

También se puede meter el script en el crontab(5) del usuario del servidor para automatizar las copias, pero eso ya es gusto de cada uno (comento más adelante).

La primera copia de seguridad tardará lo suyo (en mi caso más de 700 MB sobre SSH, normal que tarde un poco :P), pero las siguientes serán mucho más rápidas. Además he puesto la opción -v, que hace que rsync nos muestre mucha información del proceso (la podemos quitar, sobretodo si programamos las copias con cron).

En un principio ya está todo, pero vamos a prestarle un poco de atención a la parte de los enlaces fuertes. Si hacemos un par de copias de seguridad, por ejemplo introduciendo este archivo y realizando unos cambios entre copias, podemos jugar un poco con el restultado para sacar algunas conclusiones.

$ du -hs bak.*
772M    bak.0
2.0K    bak.0-info
432K    bak.1
2.0K    bak.1-info
382K    bak.2
2.0K    bak.2-info

Como podemos observar, la única copia que ocupa el espacio real es la última (bak.0 en este ejemplo), aunque en cada directorio están todos los ficheros. Podemos emplear ls(1) para verificar los nodos del sistema de archivos:

$ ls -i bak.0/Personal/jjm.jpg
783918 bak.0/Personal/jjm.jpg
$ ls -i bak.1/Personal/jjm.jpg
783918 bak.1/Personal/jjm.jpg
$ ls -i bak.2/Personal/jjm.jpg
783918 bak.2/Personal/jjm.jpg

Ese fichero no ha cambiado entre las copias de seguridad, así que comparte el espacio en disco, aunque está accesible desde las tres copias. Con lo que hemos explicado de las referencias, podemos borrar cualquiera de las tres copias, y las otras dos no se verán afectadas.

$ ls -i bak.0/Personal/rsync.html
906914 bak.0/Personal/rsync.html
$ ls -i bak.1/Personal/rsync.html
865697 bak.1/Personal/rsync.html
$ ls -i bak.2/Personal/rsync.html
865697 bak.2/Personal/rsync.html

En este otro ejemplo, que corresponde a este texto que estoy escribiendo, vemos como en las dos copias más viejas se trata del mismo fichero, pero para la más reciente he actualizado el fichero y, por lo tanto, ocupa su propio espacio en disco :).

Solo me queda comentar que es fácil automatizar este proceso, pero como es el servidor el que conecta a la estación de trabajo para realizar la copia, tendríamos que poner el trabajo en cron(8) a una hora que estemos seguros que siempre va a estar ahí la otra máquina, y modificar el script anterior para que aborte el proceso si la máquina está apagada, por ejemplo poniendo al comienzo algo como:

# Si no responde a un ping(8) la estación, abortamos
 ping -q -c 1 IP_ESTACION > /dev/null || exit

Además hay que llevar un poco de cuidado si hacemos copia de datos en uso, porque eso puede traer problemas (por ejemplo con el correo si el cliente que usamos está funcionando).

Espero que haya quedado bien explicado. Me parece bastante sencillo y el resultado es de mucha calidad. Aunque claro, siempre podemos emplear otro tipo de estrategias incluso más simples que esta ;).

Anotación por Juan J. Martínez, clasificada en: scripting, unix, security.

Hay 5 comentarios

Gravatar

interesante para copias incrementales es rdiff-backup

http://www.nongnu.org/rdiff-backup/

por un visitante, en 2006-07-20 18:13:43

Gravatar

rdiff-backup será muy interesante, pero el link esta en inglés, y Juanjo lo explica de put... madre y en español.
Felicidades por el documento Juanjo, te lo has currao. Ahora a probarlo, ya te dire como va.

por InKiLiNo, en 2006-07-20 20:10:13

Gravatar

el link (la verdad es que no sé porque no dices enlace), pero si quieres un link en castellano no cuesta mucho buscarlo (por supuesto esta entrada está bien, simplemente antes hablé de otra opción: como casi siempre con ciertas ventajas y ciertas desventajas respecto a la otra)

Una búsqueda en (elige idioma castellano)
http://www.technorati.com/search/rdiff-backup
lleva rápidamente a páginas como
http://blog.etxea.net/?p=9
http://liakona.com/wordpress/2006/04/12/cifrando-backups/

por visitante, en 2006-07-20 20:52:59

Gravatar

No conocía rdiff-backup, y la verdad es que no tengo problemas con el inglés :D De hecho lo añado a mi TODO para echarle un ojo cuando pueda :P Gracias por el enlace.

por Juanjo, en 2006-07-20 23:00:43

Gravatar

La verdad, es que tienes razón, me quejo del Inglés(es que me da rabia que los mejores documentos esten en Inglés) y en vez de decir enlace digo Link ;)
Por lo que he leido de rdiff-backup, su uso parece muy sencillo, posiblemente lo pruebe. Gracias por la info visitante.

por InKiLiNo, en 2006-07-21 08:33:39

Los comentarios están cerrados: los comentarios se cierran automáticamente una vez pasados 30 días. Si quieres comentar algo acerca de la anotación, puedes hacerlo por e-mail.

Algunas anotaciones relacionadas: