Cómo crear un sistema completo de copias de seguridad domésticas por 80 euros (II): Incremental con snapshots
Puesto que algunos lectores criticaron -con razón- la ineficacia a largo plazo del sistema un tanto "radical" de backup por imagen completa (en comparación con los backups periódicos e incrementales), hoy someto a vuestra consideración otra variante, basada -esta vez sí- en la utilidad de sincronización rsync para Linux.
Con respecto al sistema que propusimos inicialmente es obvio el ahorro de tiempo que suponen las copias incrementales, quedando ahora limitado el pesado período de espera de casi un par de horas al primer backup. Luego, las copias sucesivas estarán listas en breves minutos (unos dos o tres minutos en mi caso, que es lo que tarda rsync en guardar los cambios realizados sobre más de 100 GB).
Los parámetros disponibles en rsync son tantos que habría que aconsejar revisar su documentación y realizar pruebas en línea de comandos hasta encontrar las opciones que más nos satisfacen. Dejo este trabajo a los lectores y a los posibles comentarios. Yo he optado por una configuración bastante mínima, pero que nos permitirá realizar cuatro copias al día a las horas que especifiquemos y una copia de resguardo diaria, guardando además las de los tres últimos días. Si borro un fichero o un directorio, quiero también que desaparezca de la próxima copia, aunque continuará presente en las anteriores, lo que me permitirá recuperarlo si es que lo borré por error...
Un tema importante es la conveniencia de separar lo más posible la copia y el sistema original. Si se utiliza el mismo sistema de ficheros original para guardar la copia (aunque sea otra partición) es evidente que un fallo del disco o un pico de tensión nos pueden dejar a la vez sin original y sin copia. Mal negocio. Una idea mejor es dirigir la copia -con SSH- a otra máquina de nuestra red o a un espacio de almacenamiento remoto, pero como no todo el mundo dispone de esta posibilidad, he optado por el camino del medio: guardar la copia en otro disco, externo y diferente (sí, el mismo Maxtor 320 de la primera entrega, que el presupuesto es escaso ;)
Por último, también conviene que las copias no puedan ser sobreescritas -o borradas- por error. En sistemas exigentes y complejos hay otras formas de hacerlo, pero para un sistema doméstico vamos a utilizar una aproximación sencilla aunque bastante eficaz: montaremos la unidad de backup como "sólo lectura", obteniendo permisos de escritura sólo durante el lapso que dura la realización de la copia, y volviendo otra vez a "sólo lectura" al finalizar ésta.
¿Listo? Empezamos...
Antes de nada (y exactamente igual que en la copia de imagen completa), habrá que proceder a formatear el disco (por ejemplo, sdf) creando un sistema de ficheros ext3:
# mkfs -t ext3 /dev/sdf
Cuando finalice este proceso, montamos el disco (con permisos de lectura escritura) y creamos una serie de directorios:
# mount /dev/sdf /media/disk # cd /media/disk # mkdir backup # cd backup # mkdir hourly.0 # mkdir hourly.1 # mkdir hourly.2 # mkdir hourly.3 # mkdir daily.0 # mkdir daily.1 # mkdir daily.2
Exacto. Los directorios hourly.x albergarán las sucesivas copias horarias y los daily.x las copias diarias.
Ahora necesitaremos crear tres ficheros de texto. Dos de ellos son los scripts que se encargarán de realizar los backups horarios y las copias diarias, respectivamente. El tercer fichero contendrá un listado de aquellos ficheros o directorios que queremos excluir de las copias de seguridad.
Empezaremos por crear éste último. Se trata de un fichero de texto que habrá de contener, línea por línea, un listado de los ficheros y directorios a excluir de las copias. En mi caso he optado por copiar todo el sistema de ficheros (/) excluyendo un buen conjunto de ellos, por ejemplo, /sys, /tmp, /var/tmp..., así como los cachés de los navegadores y otras cosas del directorio personal que no merece la pena copiar. Llamo a este fichero backup_exclude y lo guardo en /usr/local/etc.
A modo de ejemplo, éste sería el contenido de un posible backup_exclude:
/dev /mnt /media /proc /sys /tmp /var/tmp /home/usuario/.mozilla/**/Cache /home/usuario/.gftp/cache /home/usuario/.opera /home/usuario/.thumbnails
Pasamos a crear los dos scripts (dos ficheros de texto al fin y al cabo, con permisos de ejecución) que se encargarán de realizar todo el trabajo. Se han separado la copia horaria y la diaria en dos scripts diferentes para programar su ejecución mejor mediante cron, y también por motivos de eficiencia (para la copia diaria basta un cp en lugar de otro rsync).
Vamos con el script que realizará nuestras cuatro copias al día, a las horas que luego especificaremos. Lo llamaremos make_snapshot.sh y lo alojaremos en /usr/local/bin, por ejemplo.
El contenido sería el siguiente (cambiando los detalles de rutas por los tuyos):
#!/bin/bash
unset PATH # evita un uso accidental de $PATH
# Alias para comandos del sistema (explora los tuyos con whereis)
ID=/usr/bin/id;
ECHO=/bin/echo;
MOUNT=/bin/mount;
RM=/bin/rm;
MV=/bin/mv;
CP=/bin/cp;
TOUCH=/bin/touch;
RSYNC=/usr/bin/rsync;
# Path de origen, destino y fichero de exclusiones
MOUNT_DEVICE=/dev/sdf;
SNAPSHOT_RW=/media/disk;
EXCLUDES=/usr/local/etc/backup_exclude;
# el script propiamente dicho
# asegurarse de que eres root
if (( `$ID -u` != 0 )); then { $ECHO "Lo siento, debes ser root. Saliendo..."; exit; } fi
# montar el destino para lectura-escritura o abortar
$MOUNT -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ;
if (( $? )); then
{
$ECHO "snapshot: no se pudo montar $SNAPSHOT_RW para lectura-escritura";
exit;
}
fi;
# rotar los snapshots de /backup
# paso 1: borrar el snapshot horario mas antiguo, si existe:
if [ -d $SNAPSHOT_RW/backup/hourly.3 ] ; then \
$RM -rf $SNAPSHOT_RW/backup/hourly.3 ; \
fi ;
# paso 2: intercambiar snapshots intermedios, si existen
if [ -d $SNAPSHOT_RW/backup/hourly.2 ] ; then \
$MV $SNAPSHOT_RW/backup/hourly.2 $SNAPSHOT_RW/backup/hourly.3 ; \
fi;
if [ -d $SNAPSHOT_RW/backup/hourly.1 ] ; then \
$MV $SNAPSHOT_RW/backup/hourly.1 $SNAPSHOT_RW/backup/hourly.2 ; \
fi;
# paso 3: crear una copia hard-link (excepto dirs) del ultimo snapshot
if [ -d $SNAPSHOT_RW/backup/hourly.0 ] ; then \
$CP -al $SNAPSHOT_RW/backup/hourly.0 $SNAPSHOT_RW/backup/hourly.1 ; \
fi;
# paso 4: hacer copia del sistema al ultimo snapshot
$RSYNC \
-va --delete --delete-excluded \
--exclude-from="$EXCLUDES" \
/ $SNAPSHOT_RW/backup/hourly.0 ;
# paso 5: actualizar mtime de hourly.0 para reflejar hora del snapshot
$TOUCH $SNAPSHOT_RW/backup/hourly.0 ;
# volver a montar el destino como solo lectura
$MOUNT -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ;
if (( $? )); then
{
$ECHO "snapshot: no se puedo montar $SNAPSHOT_RW para solo lectura";
exit;
} fi;
Por último, crearmos el script de las copias diarias. Lo llamamos daily_snapshot_rotate.sh y lo guardamos también en
/usr/local/bin. Su contenido será:
#!/bin/bash
unset PATH # evita un uso accidental de $PATH
# Alias para comandos del sistema (explora los tuyos con whereis)
ECHO=/bin/echo;
MOUNT=/bin/mount;
RM=/bin/rm;
MV=/bin/mv;
CP=/bin/cp;
# Ruta de origen y destino
MOUNT_DEVICE=/dev/sdf;
SNAPSHOT_RW=/media/disk;
# el script propiamente dicho
# asegurarse de que eres root
if (( `$ID -u` != 0 )); then { $ECHO "Lo siento, debes ser root. Saliendo..."; exit; } fi
# montar el destino para lectura-escritura o abortar
$MOUNT -o remount,rw $MOUNT_DEVICE $SNAPSHOT_RW ;
if (( $? )); then
{
$ECHO "snapshot: no se pudo montar $SNAPSHOT_RW para lectura-escritura";
exit;
}
fi;
# paso 1: borrar el snapshot diario mas antiguo, si existe:
if [ -d $SNAPSHOT_RW/backup/daily.2 ] ; then \
$RM -rf $SNAPSHOT_RW/backup/daily.2 ; \
fi ;
# paso 2: intercambiar snapshots intermedios, si existen
if [ -d $SNAPSHOT_RW/backup/daily.1 ] ; then \
$MV $SNAPSHOT_RW/backup/daily.1 $SNAPSHOT_RW/backup/daily.2 ; \
fi;
if [ -d $SNAPSHOT_RW/backup/daily.0 ] ; then \
$MV $SNAPSHOT_RW/backup/daily.0 $SNAPSHOT_RW/backup/daily.1; \
fi;
# paso 3: crear una copia hard-link (excepto dirs) de hourly.3 en daily.0
if [ -d $SNAPSHOT_RW/backup/hourly.3 ] ; then \
$CP -al $SNAPSHOT_RW/backup/hourly.3 $SNAPSHOT_RW/backup/daily.0 ; \
fi;
# ojo: no actualizar mtime de daily.0 (dejarlo igual que hourly.3)
# volver a montar el destino como solo lectura
$MOUNT -o remount,ro $MOUNT_DEVICE $SNAPSHOT_RW ;
if (( $? )); then
{
$ECHO "snapshot: no se puedo montar $SNAPSHOT_RW para solo lectura";
exit;
} fi;
Tan sólo nos resta dar permisos de ejecución a ambos scripts:
# chmod +x /usr/local/bin/make_snapshot.sh # chmod +x /usr/local/bin/daily_snapshot_rotate.sh
Programando la ejecución
Lo único que nos queda es indicarle a cron que ejecute el script de backup horario a las cuatro horas distintas del día que más puedan interesarnos. Si la máquina está permanentemente encendida la mejor opción puede ser programar la ejecución a intervalos iguales de 6 horas. Si sólo está encendida a ratos, mejor seleccionar las horas en que con mayor probabilidad vaya a estar en funcionamiento.
No indicaremos cómo utilizar cron y todas sus opciones; sólo señalaremos que Kcron nos permite hacerlo desde un entorno gráfico, aunque la costumbre nos lleva a utilizar crontab -e desde consola.
A modo de ejemplo, así le indico a cron que me ejecute el script de backup horario a las 10:00, 13:00, 18:00 y 22:00, todos los días de la semana y todos los meses del año:
# Realizar backups incrementales cuatro veces al dia 0 10,13,18,22 * * * /usr/local/bin/make_snapshot.sh
Y así añado la indicación de ejecutar el script de backup diario cada día a las 23:30:
# Realizar el backup diario una sola vez al dia 30 23 * * * /usr/bin/daily_snapshot_rotate.sh
REFERENCIAS
Este artículo es principalmente una adaptación del método utilizado por Mike Rubel en Easy Automated Snapshot-Style Backups with Linux and Rsync. Aunque el artículo tiene más de tres años, me pareció muy bien explicado y el que mejor se adaptaba a mis ideas. Llevo unos días utilizándolo y funciona sin problemas.
Iván López, amable lector de Kriptópolis, publicó hace unos meses otro artículo interesante al respecto: Rsync vs BackupPc vs Link-Backup. Es posible que para algunos lectores pueda resultar más apropiado que el método aquí expuesto. Además, Iván tiene publicado otro artículo muy majo sobre Raid 1 en Linux. Ambos artículos me parecen muy recomendables, sobre todo si nuestras necesidades van algo más allá de las de un sencillo sistema doméstico.
Como siempre, espero también que los lectores contribuyan a mejorar o afinar el método aquí expuesto, aunque les ruego que traten de no olvidar que el público al que nos dirigimos es el de usuarios domésticos, con un nivel de necesidades no muy alto. En cualquier caso, las sugerencias y posibles mejoras siempre son bienvenidas.
También en Kriptópolis:

- 4663 lecturas
Twitter

Excelente
Me parece un excelente articulo.. existe la posibilidad de hacerlo en güindows??
Muy buen aporte...
y el restore?
estaría bueno que al howto le agreguen el método para hacer una restauración a una fecha indicada. Así quedaría completito el howto :)
No hay problema
Al tratarse de una copia exacta pueden restaurarse ficheros con un simple cp (o un cp -a para restaurar directorios de forma recursiva).
Estupendo
Estupenda guía para no iniciados. Sólo tengo dos preguntas:
1) ¿Por qué conservas el sistema completo? ¿No basta con /home y algún otro directorio particularmente sensible (/var/www, se me ocurre)? En caso de catástrofe posiblemente sea más seguro instalar el sistema otra vez que recuperarlo de una copia.
2) ¿¡No cifras las copias!?
SKS, criptografía de curva elíptica de bolsillo
http://sks.merseine.nu
SKS, criptografía de curva elíptica de bolsillo
http://sks.anarres.tk
Buenas preguntas
a la 1... casi completo sí, pero supongo que es sólo una manía.
a la 2... no, en casa del herrero... Ya sabes: como no tengo nada que ocultar ;)))))))
Tengo otra idea
Este articulo si que me ha gustado, mas que el primero, felicidades.
Esta es mi propuesta. (Pero no puedo implementarla)
Si nuestro presupuesto llega hasta los 160 € podemos usar el disco externo y un servidor de discos en red como este www.nslug.es (Al que se le puede conectar dos discos externos)
Además como nos queda libre otro puerto USB para conectar otro disco, lo podemos configurar como equipo P2P de bajo consumo.
Ya tan solo nos quedaría configurar Rsyn en el cacharrito y en los equipos.
Y si tenemos equipos con Windows o con Mac también podemos usar Rsyn como bien indica la wikipedia es.wikipedia.org/wiki/Rsync
Saludos.
Un matiz en la hora del snapshot
Magnífico trabajo. Tomo nota y me lo apunto, que el de las copias de seguridad es uno de mis temas pendientes.
Permíteme un retoque quizás algo puntilloso. En su día también me dedicaba a programar copias de seguridad y entonces me encontré el mismo problema. Me explico:
En mi opinión, en el script make_snapshot.sh que ejecutas 4 veces al día, deberías intercambiar el orden de los pasos 4 y 5: primero anotar la hora a la que empiezas y luego lanzar el rsync (ya sé que se complica el comando touch, que debe llevar un parámetro más).
Lo digo porque si usas esa hora para comprobar ficheros modificados desde el último snapshot, y da la casualidad de que algún fichero se modifica justo en el intervalo entre que se le ha hecho rsync y se modifica el mtime, ese fichero se queda en el "limbo" de los modificados pero que no se tiene constancia de ello.
Gracias por un trabajo bien hecho.
Un articulo muy bueno pero...
...resulta que todo esta ya esta hecho, y ademas basado en el mismo articulo, supongo, porque los nombres por defecto de los directorios son los mismos:
www.rsnapshot.org
Yo estoy usando rsnapshot en produccion en 2 servidores mios, y en varios clientes. La funcionalidad de ofrecer por samba una vista readonly del area de backup es impagable: nadie me llama para restaurar un fichero ;-D
Respecto al amigo que indica que si se puede hacer en Windows, estoy casi seguro de que si, con CYGWIN, e instalando rsync. Mi duda era si se podría por el tema de los hard links en NTFS, pero resulta que he averiguado que NTFS SI tiene hard links, y CYGWIN los soporta, asi que supongo que rsync tambien.
Normal
No se trata de una tesis inédita, sino de un método típico y establecido que yo mismo he adaptado desde la página que cito.
Claro
No, si yo no te quito merito, simplemente comentaba que alguien ya lo hizo antes (si, el anonimo anterior soy yo :-).
Rsnapshot esta basado en exactamente el mismo articulo que mencionas, pero es algo mas comodo: puedes cambiar la periodicidad de los backups, el numero, el período de retencion, permite ejecutar scripts previos a la copia de seguridad (p.e. para ejecutar un volcado de una base de datos), y sobre todo permite hacer copias de equipos remotos accediendo a ellos mediante SSH. Todo ello desde un fichero de configuracion, sin tocar script. Con rsnapshot puedes montar un servidor de backup cojonudo con muy poco trabajo.
Hasta tiene un libro de O'Reilly.
Lo dicho, que no te quito mérito, pero Rsnapshot esta mucho mas pulido y probado. En serio, pruebalo, no te arrepentirás.