Hoy en día existen muchas soluciones para realizar un backup de ficheros en Linux y otros sistemas operativos . Sin embargo quizás prefieras en ocasiones componer tu propio script que realice algún tipo de backup especial.
En mi caso no suelo necesitar ser especialmente puntilloso con las copias de seguridad. Con realizar una copia de seguridad completa de mis archivos semanalmente es suficiente. No tengo que realizar copias incrementales o diferenciales y por ese motivo no me compliqué mucho la vida.
Copias de seguridad con rsync
En el script que incluiré comentado a continuación para realizar copias de ficheros parto de la base que necesito dos tipos de copias:
Por un lado una única copia completa de todos mis ficheros de música, documentos, películas, fotografías, etc. Son ficheros que simplemente no cambian de versión o contenido, por lo que no tiene mantener copias diferenciales o incrementales. Con este tipo de contenidos simplemente me limito a sincronizar el directorio destino con los nuevos ficheros a incluir (o eliminar).
En segundo lugar están los archivos que sí podrían tener distintas versiones a lo largo del tiempo. Por ejemplo el contenido de /etc, /var/www o de /var/lib. Estos directorios simplemente los almaceno en la máquina de destino. Podría comprimirlos en un solo fichero, pero la verdad. Cuando necesito recuperar un fichero o su contenido prefiero no tener que ir buscándolo, así que simplemente me limito a copiar el directorio.
Como veis no es un tipo de copia complejo pero aunque pueda sonar raro, quizás sea lo menos importante de este script dado que como veréis se puede cambiar fácilmente para que realice copias comprimidas, incrementales, etc. Me parecen mucho más interesantes otros aspectos en este script como:
- Facilidad de adaptar el script a otros servidores
- Desarrollo de funciones que informen del estado de las copias y procesos finalizados
Conexión sin contraseña por SSH
Lo que no he comentado todavía es que para que funcione automáticamente la conexión con el servidor de backup y no solicite contraseña cuando se ejecute deberemos de conectarnos mediante una clave pública.
Cualquier proceso de copia entre servidores debe de realizarse con las debidas garantías, así que una conexión SSH es lo mejor. Es un proceso muy sencillo y seguro que deberemos de realizar previamente a la ejecución del script para que ambas máquinas se conecten sin nuestra intervención, pero recuerda que deberas de realizar este proceso previo a la implementación del script de backup.
Un script para todas las máquinas
En sí realizar el script es muy sencillo. Con un par de arrays en donde incluyamos las rutas de directorio que queramos realizar cada uno de los tipos de copia es suficiente. Sin embargo utilizando variables podemos hacer que nuestro script funcione en cualquier servidor sin tener que tocar nada del código cada vez que instalemos una nueva máquina. Y si no tuviéramos que hacer nada salvo copiar el script y asociarlo a una tarea cron mucho mejor. Por este motivo casi toda la configuración en variables las obtiene del propio sistema.
#!/bin/bash # Common Vars date=$(date +%Y%m%d) user="adminuser" domain=$(dnsdomainname) localHost=$(hostname) backupHost="servidor_de_backup.your_domain.tld" log="files_backup.log" |
En el apartado de variables simplemente incluiremos toda la información relativa al servidor de destino backupHost
y user
el nombre de usuario que utilizaremos para conectar con él. El resto de información la obtiene del propio sistema como el hostname, hostdomain, la fecha. Es conveniente que antes e ejecutar el script te asegures tener instalados estos comandos.
Configuración de los directorios a realizar copia y su tipo
Como decía antes distingo entre dos tipos de copias. Por un lado directorios a sincronizar y en sgundo lugar directorios sobre los cuales realizar una copia completa cada vez que se ejecute el script, albergando cada copia con un directorio por fecha.
# Array of dirs to sync syncDirs=("/store/img/" "/store/mp3/" "/store/docs/" "/store/video/" "/store/mail/" ) # Array of dirs to backup backupDirs=("/etc/" "/store/web/" "/var/lib/mysql/" ) |
Funciones
Antes de llegar a los dos procesos en sí me gustaría explicar las dos funciones que utilizo en este script.
La primera de ellas es evalOperation() que simplemente evalúa si la operación (de copia) ejecutada anteriormente devuelve un error o se ha realizado correctamente, para posteriormente informar en el log. La segunda de ellas es sendMailStatus() que simplemente es un función que nos permite enviar cualquier tipo de contenido en HTML via email a root.
Como veis ambas son muy sencillas y se pueden reutilizar en otros scripts.
function evalOperation() { if [ $1 -gt 0 ]; then local result="<span style="color: #F00">fail</span>" else local result="<span style="color: #0F0">OK</span>" fi echo $result return 0 } function sendMailStatus() { mail -s "$1" -a "MIME-Version: 1.0" -a "Content-Type: text/html" root@$domain < $2 return $? } |
La ejecución del script
Como podréis ver la ejecución es muy sencilla dado que no realizo ningún tipo de copia compleja. Ejecuto primero la acción de sincronizar el contenido de los directorios del primer array; mientras que en segundo lugar simplemente ejecuto la copia de los directorios en una carpeta con la fecha de ejecución del script.
Como paso previo borramos el contenido del fichero de log y en último lugar después de realizar la tarea de copia informamos por email al administrador del sistema si ha funcionado correctamente todo.
# Reset log cat /dev/null > $log # Syncing dirs for originDir in "${syncDirs[@]}"; do destDir=/backup/${originDir#/store/} rsync -avhiz --delete $originDir $user@$backupHost:$destDir result=$(evalOperation $?) echo "<p>Sync of dir $originDir [$result]</p>" >> $log done # Backup dirs for backupDir in "${backupDirs[@]}"; do ssh $user@$backupHost "mkdir -p /backup/machines/$localHost/$date$backupDir$" rsync -avi --delete $backupDir $user@$backupHost:/backup/machines/$localHost/$date$backupDir result=evalOperation $? echo "<p>Backup of dir $backupDir [$result]</p>" >> $log done # Sending mail sendMailStatus "Backup of files in $localHost done $date" $log |
Últimos detalles
Sin embargo el espacio no es infinito en nuestro servidor de backup. La copia de directorios en carpetas organizada por fecha seguramente en algún momento desbordará el espacio de disco disponible. Por ese motivo es interesante complementar este proceso con una evaluación del número máximo de copias queremos tener y elimine las sobrantes.
# Vars log="rotate_backup.log" backupPath="/backup/machines/" oldCopies=($(ssh $user@$backupHost "ls $backupPath$localHost | sort -r")) maxNumOfCopies=3 # Log file cat /dev/null > $log # If they are more than the max of copies if [ ${#oldCopies[@]} -gt $maxNumOfCopies ]; then # Unset of array values with index < of maxNumOfCopies i=0 while [ $i -lt ${#oldCopies[@]} ]; do if [ $i -lt $(( $maxNumOfCopies )) ]; then unset oldCopies[$i] fi let "i++" done # We remove the old copies for copy in ${oldCopies[@]}; do ssh $user@$backupHost "rm -rf $backupPath/$localHost/$copy" result=$(evalOperation $?) echo "<p>Removing copy of $copy [$result]</p>" >> $log done fi if [ ! -s rotate_backup.log ]; then echo "<p>No copies to delete<p>" >> $log fi # We send a email sendMailStatus "Removing old copies of $localHost done $date" $log |
Como podéis ver el número máximo de copias que incluyo es tres, pero hasta eso podría modificar. También vuelvo a utilizar sendMailStatus() para enviar correo y evalOperation(). Este código lo podríamos ejecutar después de realizar la copia.
Y por último configurar un cron
Ya lo único que nos quedaría sería planificar una tarea de cron para lanzar nuestro script a una hora de baja actividad y realice la copia. Por ejemplo los domingos a la 1 AM.
Espero que os sea de utilidad. Como ya os dije no es un proceso especialmente sofisticado, pero creo que muy flexible a la hora de configurarlo para adaptarlo a vuestras necesidades. Este script realmente no es mas que una parte de un conjunto de scripts que ejecuto secuencialmente para realizar distintas tareas de copia de ficheros, mantenimiento, copia de Bases de Datos, etc. Incluyendo el encendido y apagado de máquinas remotas para realizar el backup. Pero por hoy es suficiente. 😉
Autor:
Última actualización:
Excelente articulo, a partir de este voy a tratar de modificarlo para que únicamente me realize backup de todos los emails (/var/qmail/mailnames/) en una maquina local.
Solo una duda, todo el código que as indicado aquí, iría correlativamente en un fichero .sh?
Gracias por tu comentario.
Sí todo el código iría en un .sh. Pero también puedes separar procesos e ir lanzando distintos .sh uno tras otro para distintas tareas. Es un modo de separar procesos y además ante cualquier fallo es más sencillo depurar.
Hola Oscar;
Gracias por este articulo, me fue genial, solo quería comentarte una cosa, el link de conectarnos mediante clave pública cambio y el nuevo es este http://tuxapuntes.com/2014/08/como-conectar-por-ssh-sin-password-generar-autenticacion-de-clave-publica-rsa/
Un saludo y gracias de nuevo.
Salu2.
Gracias Germán por tu aporte y ayudarme a mantener actualizado el blog. Lo actualizo.