No hace falta decir la importancia que tiene realizar copia de seguridad de nuestros ficheros y bases de datos. Además es conveniente tener una política clara a la hora de realizarlas, mejor aún si podemos almacenarlas en una máquina en una ubicación distinta a la del servidor de producción o desarrollo. Este post simplemente recoge una posible implementación de un script bash que se podría asociar a una tarea cron que realice una copia con mysqldump de nuestras bases de datos en MySQL.

ACTUALIZACIÓN: Agradeciendo el aporte a Pedro García Martínez hay que mencionar por supuesto otros scripts como AutoMySQLBackup tremendamente configurables que permite rotación de copias, pre y post-procesos, compresión, envío de emails, etc.

Características de este script

Algunos de los aspectos más destacables de este script:

  • Empleo de mysqldump: Utilizamos una de las utilidades incluidas en el paquete de MySQL para realizar backup sin detener el servidor. Es tremendamente configurable, por lo que incluyo un enlace a su documentación por si quieres personalizarlo.
  • Almacenamiento por fecha. No sólo es importante guardar una copia de seguridad de los datos, sino distintas versiones por si queremos recuperar datos que no están contenidas en la última copia. Este script crea una carpeta con la fecha de creación de la copia.
  • Almacenamiento en un servidor remoto. Tener una copia de los datos fuera del mismo entorno físico del servidor original es una buena práctica de seguridad. Para ello lanzamos una conexión SSH que nos permita conectar con el servidor remoto, lo cual además nos ofrece una conexión encriptada para realizar la copia. Esto sin embargo nos obliga a poder conectar por SSH con el servidor de backup sin password. Aquí tienes un sencillo tutorial sobre ssh-keygen y ssh-copy-id para configurarlo.
  • Blacklist de BD a ignorar. Generalmente se realiza una copia de todas las Bases de datos, pero hemos incluido una “blacklist” para aquellas que no queremos mantener copia, como “information_schema” y “performance_schema”. O si por ejemplo tuvieramos bases de datos de desarrollo de las cuales no nos interesa mantener copia podríamos incluirlas en la declaración de este array.
  • Facilmente configurable. Básicamente sólo tenemos que configurar tres variables con los datos del servidor donde queremos almacenar el backup: backupUser, backupHost y backupDir.
  • Fácilmente transportable. Sin cambiar ningún dato de la configuración del script podemos utilizarlo en distintos servidores. En el caso de Debian se almacenan las credenciales de administración en “etc/mysql/debian.cnf” así que hacemos uso de ello para no tener que incluir en un script esos datos. Simplemente incluyendo este script en cada servidor que queramos realizar copia y asociándolo a una tarea cron realizará la copia cuando le indiquemos.
  • Envío de correo con el status de la copia. Una vez finalizada la tarea de copia envía un correo electrónico con el resultado de la copia de cada una de las bases de datos al usuario root del dominio del máquina.

El script

Bueno, os dejo una copia del script. Espero os sea de utilidad. Una última cosa: este script debe de ejecutarse con permisos de root o de lo contrario no tendrá acceso a /etc/mysql/debian.cnf y no realizará las copias.

#!/bin/bash
 
# Include functions
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
}
 
containsElement() {
local n=$#
local value=${!n}
for ((i=1;i < $#;i++)) {
if [ "${!i}" == "${value}" ]; then
return 1
fi
}
return 0
}
 
sendMailStatus() {
mail -s "$1" 
-a "MIME-Version: 1.0" 
-a "Content-Type: text/html" 
root@$domain < $2
return 0
}
 
# Vars
date=$(date +%Y%m%d)
domain=$(dnsdomainname)
localHost=$(hostname)
backupUser="adminuser" # your backup server user
backupHost="dana" # your backup server
backupDir="/backup/machines" # your backup dir
log="mysql_backup.log"
 
# Obtaining list of Databases
databases=(
$(for i in $(mysql --defaults-file=/etc/mysql/debian.cnf -Bse "show databases;")
do echo $i
done) 
)
 
# Blacklist DB
avoidDatabases=("information_schema" "performance_schema")
 
# We blank the log
cat /dev/null > $log
 
# We create the dir where we store the backup
ssh $backupUser@$backupHost "mkdir -p $backupDir/$localHost/$date/mysql"
 
# We iterate trough the loop
for db in ${databases[@]}; do
$(containsElement ${avoidDatabases[@]} "$db")
if [ $(echo $?) == 0 ]; then
mysqldump --defaults-file=/etc/mysql/debian.cnf $db | ssh $backupUser@$backupHost "dd of=$backupDir/$localHost/$date/mysql/$db.sql"
# We check for errors
result=$(evalOperation $?) # We check the errorlevel of the last command
echo "&lt;p&gt;Backup of DB $db [$result]&lt;/p&gt;" >> $log
fi
done
 
# We send a email
sendMailStatus "MySQL backup in $localHost done $date" $log
Comparte si te ha gustado

Autor:
Última actualización:

4 comentarios

    1. Muchas gracias Manuel por tu comentario.

      Sí es más rápido con mysqlhotcopy porque realizas una copia binaria de los datos en lugar de obtener un volcado SQL. Sin embargo esa opción tiene dos inconvenientes: primero, sólo puedes realizar esta operación con BD basadas en el motor MyISAM y no con InnoDB; y segundo, al ser una copia binaria deberás de restaurarlo en el mismo servidor MySQL o con con la misma versión. De lo contrario podrías tener problemas.

      Si realmente la BD es muy grande y va a llevar mucho tiempo es recomendable utilizar una política con dos servidores, master y slave. El backup lo realizas a partir de la DB en el master y mientras no dejas de ofrecer el servicio en el slave, por ejemplo. http://dev.mysql.com/doc/mysql-backup-excerpt/5.6/en/replication-solutions-backups-read-only.html

Deja un comentario

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.