En estos días tuve que configurar unos backups para un cliente. Algo bastante sencillo. Tenía dos servidores y necesitaba hacer backups de distintas cosas en cada equipo y copiarlos al otro. Por supuesto, la herramienta clave para esto es rsync. Googleando un poco vi que existe esta página donde se puede ver cómo generar snapshots incrementales automáticos usando hard links y rsync. Realmente es una solución muy interesante, pero a mí no me terminaba de convencer porque yo quería tener archivos comprimidos que fueran rotando.
Por lo tanto lo que hice fue, seguramente, reinventar la rueda una vez más. Hice una pequeña librería en BASH que luego reutilicé en los distintos scripts de backup que hice. La clave aquí es la función “create_archive” que toma un path, un nombre de archivo base y una lista de archivos, y se ocupa de ir al path, ver todos los archivos que haya con ese patrón de nombre básico, rotarlos y generar un nuevo tar.gz. Después agregué un par de funciones más que me venían bien, “log” para registrar todo lo que pasaba en un archivo, “mail_notification” para mandarme mails y “sync_backup_servers” para ejecutar rsync.
El código:
CONF_FILE="/home/sysbackup/scripts/backup.conf"
if [ -f $CONF_FILE ]; then
. $CONF_FILE
else
echo "Configuration file $CONF_FILE not found"
exit 1
fi
RM_BIN="/bin/rm"
TAR_BIN="/bin/tar"
MAIL_BIN="/bin/mail"
RSYNC_BIN="/usr/bin/rsync"
function log
{
echo "`date`: $*" >> $LOG_FILE
}
function mail_notification
{
subject="$1"
message="$2"
if [ -z "$subject" ]; then
subject="Backup Notification"
fi
if [ -z "$NOTIFICATIONS_MAILS" ]; then
log "mail_notification: empty recipients list"
return 1
fi
if [ -z "$message" ]; then
log "mail_notification: empty message"
return 1
fi
sysdata="Date: `date`\nHost: `hostname`"
echo -e "$message\n\n$sysdata" | $MAIL_BIN -s "$subject" "$NOTIFICATIONS_MAILS"
}
function sync_backup_servers
{
log "Running rsync from $LOCAL_DIR to $REMOTE_DIR as $RSYNC_USER"
su -c "$RSYNC_BIN -aq –delete -e ssh $LOCAL_DIR/ $REMOTE_DIR/ 2>> $LOG_FILE" $RSYNC_USER
if [ $? -eq 0 ]; then
log "Syncronization complete successfuly"
else
log "Syncronization finished with errors"
fi
}
function create_archive
{
file_path="$1"
file_name="$2"
files="${*:3}"
if [ -z $file_path ]; then
echo "Missing file path"
return 1
fi
if [ -z $file_name ]; then
echo "Missing file name"
return 1
fi
if [ -z $files ]; then
echo "Missing file list"
return 1
fi
if [ -z $MAX_BKP_FILES ]; then
MAX_BKP_FILES=4
fi
archive_name="${file_name}_`date +%Y%m%d`.tar.gz"
log "Preparing to create $archive_name archive"
# Begin to Rotate files
# Sort files by date and keep the latest ones
# MAX_BKP_FILES will determine how many to store
dir=`ls -t $file_path/${file_name}_*.tar.gz 2> /dev/null`
if [ $? -eq 0 ]; then
N=0
for file in $dir; do
if [ $N -lt $MAX_BKP_FILES ]; then
let N++
else
log "Removing old file $file"
$RM_BIN -f $file
fi
done
else
log "No other archive found on $file_path"
fi
log "Creating tar archive $file_path/$archive_name"
$TAR_BIN zcf "$file_path/$archive_name" $files 2>> $LOG_FILE
}
Algunas consideraciones importantes.
Configuración
Al principio del script lo que hago es incluir un archivo de configuración con algunas variables básicas que voy a utilizar. Este archivo debería ser algo similar a esto:
LOCAL_DIR="/home/sysbackup/backup/server1.domain.com"
REMOTE_DIR="sysbackup@server1.domain.com:/home/sysbackup/backup/server1.domain.com"
LOG_FILE="/var/log/sysbackup.log"
MAX_BKP_FILES=4
NOTIFICATIONS_MAILS="admin@email.com"
RSYNC_USER="sysbackup"
LOCAL_DIR es el directorio local base donde van a estar mis backups. REMOTE_DIR es el directorio equivalente en el otro servidor. Lo que hice fue crear un usuario “sysbackup” (un poco menos obvio que “backup”, pero también self-explanatory) en los dos servidores y generar llaves para que se puedan conectar por SSH entre los dos servidores. Luego en la /home de cada usuario creé una carpeta “backup” y adentro de ella una carpeta para cada host que iba a ser backupeado “server1.domain.com” y “server2.domain.com”.
LOG_FILE indica el archivo donde se van a guardar los logs del backup y MAX_BKP_FILES determina la cantidad máxima de archivos de backup que va a haber por cada elemento.
Rotación
Como dije, la función más importante es create_archive. La pensé para logs que se crean una vez por día (o cada más tiempo), por lo que si la quieren usar para rotar logs generados en intervalos de tiempo más cortos van a tener que modificarla. Lo que hace es generar un nombre de archivo con una raiz elegida por nosotros (digamos “db”) y la fecha actual (la función pone la fecha, pero si necesitan intervalos más cortos van a tener que poner fecha y hora). Luego hace un `ls -t` del directorio donde hay que generar el backup para ver si hay otros archivos que coincidan con el patrón del nombre correspondiente (por ejemplo, ‘db_*.tar.gz’). Si hay archivos, va a conservar los últimos 4 (en realidad la cantidad la determina MAX_BKP_FILES) y va a borrar los más viejos. Por último, va a generar el tar.gz con la lista de archivos que le hayamos pasado.
Ejemplo:
Va a generar con un archivo de nombre como “web_20100902.tar.gz” en la carpeta $LOCAL_DIR/web con todos los contenidos de /var/www/html.
Rsync
La función sync_backup_servers hace la sincronización entre los dos servidores usando rsync por SSH. Una cosa a tener en cuenta es que en mi caso, yo necesitaba que el script de backup corriera como root (para poder acceder a todos los archivos que había que backupear) pero quería que el rsync se ejecutara con el usuario sysbackup (para mayor seguridad). Por lo tanto la función usa “su -c sysbackup”. Si a uds. este enfoque no les sirve pueden poner en la función directamente:
Notificaciones por mail
Es muy útil poder tener notificaciones por mail, sobre todo cuando las cosas andan mal. El comando “mail” de Linux/Unix es muy útil para esto. La funcion mail_notification usa ese comando para mandar un mail con el mensaje que queramos y le agrega dos datos útiles: la fecha y el hostname desde el que se manda. En realidad son datos que siempre viajan en los headers del mail, pero a mí me parecía útil que estuvieran en el body.
Espero que les sirvan estos recursos. No son una solución completa y cerrada, sino herramientas que quizás les sirvan para implementar o al menos pensar cómo hacer sus propios sistemas de backup. Les recomiendo enfáticamente que lean este artículo sobre cómo generar backups con rsync porque explica muchas cosas fundamentales.


Esta noche tenía un ratito y me puse a jugar con la Eee PC que 