2

Script para obtener y subir backups de postgres a Google Cloud Storage y avisar con correo electrónico

TLDR;

Dejo el repositorio final del script. backup-postgres
Con este obtendremos subir un zip por cada base de datos en postgres de un servidor, subirlo a Google Cloud Storage y luego enviar un correo para notificar al administrador.

Motivación

En mi oficina administramos varios servidores de Odoo con muchas bases de datos en cada uno. Conforme fue creciendo la empresa, estas bases de datos se fueron haciendo más numerosas y los servidores de la misma forma, y el tema de los backups, que antes podía manejarlos manualmente, ahora se complica mucho.
Gracias al curso de Curso de Programación en Bash Shell pude encontrar la solución a este dilema, no solamente logrando obtener el backup de todas las bases de datos, sino también subiéndolo a Google Cloud Storage y finalmente, enviando un aviso al administrador del sistema de que la copia fue realizada con éxito.
Ni mencionar que esto se puede automatizar y ser realizado todos los días, así que les comparto mi experiencia 😃

Configuración inicial

Para lograr todo lo mencionado, necesitaremos algunas cosas en el servidor:

  • Crear la carpeta /var/backups/databases donde guardaremos las bases de datos
  • Instalar zip para comprimir los respaldos
  • Instalar gcloud e iniciar sesión
sudo mkdir /var/backups/databases
sudo apt-get install -y zip
export CLOUD_SDK_REPO="cloud-sdk-$(lsb_release -c -s)"
echo "deb http://packages.cloud.google.com/apt $CLOUD_SDK_REPO main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo apt-keyadd -
sudo apt-getupdate && sudo apt-getinstall -y google-cloud-sdk
gcloud init

El último comando iniciará un asistente para iniciar sesión con tu cuenta de Google Cloud. Es importante seguir las indicaciones y colocar el proyecto donde estará nuestro bucket de respaldos.

Obtener las bases de datos

Esto fue el primer desafío. con el comando psql -l -t obtenemos el listado de las bases de datos:

usuario@PC:~# psql -l -t
 bd10_aceros     | usuario  | UTF8      | C       | C     |  
 postgres        | postgres | SQL_ASCII | C       | C     |
 proxy10         | postgres | UTF8      | C       | C     |
 template0       | postgres | SQL_ASCII | C       | C     | =c/postgres          +
                 ||||| postgres=CTc/postgres
 template1       | postgres | UTF8      | C       | C     |

Ahora, debemos filtrar dicho comando:

usuario@PC:~# psql -l -t | cut -d'|' -f1 | sed -e 's/ //g' -e '/^$/d'
bd10_aceros
postgres
proxy10
template0
template1

Perfecto! Es hora de iniciar nuestro programa bash.

Creando el archivo pg_backup_all.sh

En mi caso, le puse el nombre pg_backup_all.sh, y lo primero que debemos hacer es declarar nuestras variables principales.

#!/bin/bash# Nombre del Bucket en Google Cloud Storagegoogle_bucket="conflux-backups"# Directorio de los respaldosbackup_dir="/var/backups/databases/"# Correo de gmail remitentegmail_from="[email protected]"# Contraseña de gmail remitentegmail_pwd="123456"# Correo receptorgmail_to="[email protected]"# Formato de fecha para agregar a los backupsbackup_date=`date +%Y-%m-%d`
# Numero de dias que puede estar una copia (eliminaremos las mas antiguas)number_of_days=3

Crearemos un archivo mail.txt con un contenido de saludo:

From:"Backup de Postgres" <[email protected]>
Subject: Resultado de Backups Cloud

Querido Administrador,
se han realizado con exito los backups solicitados.
Se listan a continuacion todas las bases rescatadas y subidas a Cloud Storage:

Agregaremos el comando para obtener todas nuestras bases de datos y lo pondremos en un bucle para poder obtener un backup por cada una:

databases=`psql -l -t | cut -d'|'-f1 | sed -e's/ //g'-e'/^$/d'`
# 
cp mail.txt out.txt
for i in$databases; doif [ "$i" != "postgres" ] && [ "$i" != "template0" ]; thenecho Dumping $i to $backup_dir$i\_$backup_date.sql 
  fidone
  • Nota: Agregaremos un if para evitar sacar backups de bases de datos no necesarias, como postgres o template0.

Ahora tenemos que llenar la parte de adentro del bucle. Crearemos el backup con el comando pg_dump, luego comprimiremos dicho archivo con zip. Después de comprimido lo subiremos a Google Cloud Storage mediante la herramienta gsutil y generaremos una línea por el backup hecho para agregar al archivo mail.txt. Este archivo lo estamos generando de a pocos para al final enviarlo como correo electrónico.

for i in$databases; doif [ "$i" != "postgres" ] && [ "$i" != "template0" ]; thenecho Dumping $i to $backup_dir$i\_$backup_date.sql    
    pg_dump $i > $backup_dir$i\_$backup_date.sql
    #zipping sql
    zip $backup_dir$i\_$backup_date.zip $backup_dir$i\_$backup_date.sql
    #uploading to google cloud
    gsutil cp $backup_dir$i\_$backup_date.zip $google_bucket#printing file size to mail
    file_size=$(du -m $backup_dir$i\_$backup_date.zip | cut -f1)
    echo Backup de $i\_$backup_date.zip $file_size MB >> out.txt
  fidone

Agregaremos una eliminación de archivos que sean mayores a la cantidad de días configurada inicialmente:

#removing old files
find $backup_dir -type f -prune -mtime +$number_of_days -exec rm -f {} \;

Ya acabamos. Solamente falta que enviemos un correo con el contenido de nuestro archivo antes generado al correo configurado.

curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd --mail-from $gmail_from --mail-rcpt $gmail_to --upload-file out.txt --user $gmail_from:$gmail_pwd --insecure
  • Nota: Si se desea enviar a varios destinatarios, bastará que agreguemos un –mail-rcpt en la línea de comandos.

Script completo

#!/bin/bash# Nombre del Bucket en Google Cloud Storage
google_bucket="conflux-backups"# Directorio de los respaldos
backup_dir="/var/backups/databases/"# Correo de gmail remitente
gmail_from="[email protected]"# Contraseña de gmail remitente
gmail_pwd="123456"# Correo receptor
gmail_to="[email protected]"# Formato de fecha para agregar a los backups
backup_date=`date +%Y-%m-%d`
# Numero de dias que puede estar una copia (eliminaremos las mas antiguas)
number_of_days=3
databases=`psql -l -t | cut -d'|'-f1 | sed -e's/ //g'-e'/^$/d'`
cp mail.txt out.txt
for i in$databases; doif [ "$i" != "postgres" ] && [ "$i" != "template0" ]; thenecho Dumping $i to $backup_dir$i\_$backup_date.sql    
    pg_dump $i > $backup_dir$i\_$backup_date.sql
    #zipping sql
    zip $backup_dir$i\_$backup_date.zip $backup_dir$i\_$backup_date.sql
    # subiendo a google cloud
    gsutil cp $backup_dir$i\_$backup_date.zip $google_bucket#printing file size to mail
    file_size=$(du -m $backup_dir$i\_$backup_date.zip | cut -f1)
    echo Backup de $i\_$backup_date.zip $file_size MB >> out.txt
  fidone# eliminando archivos antiguos
find $backup_dir -type f -prune -mtime +$number_of_days -exec rm -f {} \;
# ahora enviamos mail de ejecucion correcta
curl --url 'smtps://smtp.gmail.com:465' --ssl-reqd --mail-from $gmail_from --mail-rcpt $gmail_to --upload-file out.txt --user $gmail_from:$gmail_pwd --insecure

Ejecución

Para poder ejecutarlo, primero se le debe otorgar permisos de ejecucion:

chmod +x pg_backup_all.sh

Luego simplemente podemos llamarla como un ejecutable:

./pg_backup_all.sh

Automatización

Para agregarlo como tarea automática en el servicio cron del servidor, debemos abrir el editor de cron:

crontab -e

Luego añadir una línea haciendo referencia a nuestro script.

30 2 * * * /opt/backup-postgres/pg_backup_all.sh

Conclusión

Podemos modificar este script para que use FTP (como aprendemos en el (curso de Platzi)[https://platzi.com/clases/bash-shell/]) o para que suba los archivos a S3. Podemos cambiar el aviso de correo por simplemente un registro en una API, etc.
En realidad, las posibilidades son infinitas, esta fue mi colaboración lograda después de completar el curso. Les recomiendo completarlo ya que como administrador de servidores me ha ayudado muchísimo a organizar mis servidores y aprender a administrarlos de una manera más eficiente.

Escribe tu comentario
+ 2
3
8440Puntos

Gracias por la información, muy útil.

2
3380Puntos

Excelente, me ayudó a resolver un problema.

1
45027Puntos
2 años

me alegra que ayude 😃