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 "<p>Backup of DB $db [$result]</p>" >> $log fi done # We send a email sendMailStatus "MySQL backup in $localHost done $date" $log |
Autor:
Última actualización:
Buen post y buen aporte el script. No obstante yo soy más de mysqlhotcopy, cuando la base de datos es grande mysqldump puede dejarte la base de datos inoperativa durante un tiempo.
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
Muy interesante tu post y tu web, con tu permiso te añado a favoritos.
Un cordial saludo.
¡Un seguidor! Muchas gracias.
Intentaré seguir introduciendo más post sobre Linux y desarrollo web. Por cierto… Muy recomendable también tu página: http://dias.dyndns.biz
Salu2.
10 PM , 2024, Cuba , y aca, leyendo tu post hahaha, muchas gracias por compartir tu experiencia.