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 "&lt;p&gt;Sync of dir $originDir [$result]&lt;/p&gt;" >> $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 "&lt;p&gt;Backup of dir $backupDir [$result]&lt;/p&gt;" >> $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 "&lt;p&gt;Removing copy of $copy [$result]&lt;/p&gt;" >> $log
  done
fi
 
if [ ! -s rotate_backup.log ]; then
  echo "&lt;p&gt;No copies to delete&lt;p&gt;" >> $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. 😉

Comparte si te ha gustado

Autor:
Última actualización:

4 comentarios

  1. 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?

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

De acuerdo con lo dispuesto en el Reglamento (UE) 2016/679 de 27 de abril de 2016, consiento que mis datos sean tratados bajo la responsabilidad de Oscar Gascón Arjol para recibir respuesta a consultas. publicación de comentarios del blog y que las conserve mientras haya un interés mutuo para ello. Me doy por informado que tengo derecho a revocar este consentimiento en cualquier momento y a ejercer los de acceso, rectificación, portabilidad y supresión de mis datos y los de limitación y oposición al tratamiento dirigiéndome por email a me@oscargascon.es. También estoy informado de que puedo reclamar ante la autoridad de control a www.agpd.es.