Scripts para realizar exports e imports de MySQL y PostgreSQL

Al haber trabajado en muchas ocasiones con motores de bases de datos MySQL y PostgreSQL en entornos Unix-Like, he creado unos scripts bash que permiten realizar fácilmente exports e imports de las bases de datos albergadas en dichos motores.

Con configurar unas pocas variables de los scripts ya los podrán tener funcionando en su entorno de trabajo, cuyo uso, aparte de ser muy sencillo, espero que les sean de mucha utilidad.


Script de exportación

Comenzamos por el script de exportación, encargado de generar un archivo dump fechado de nuestra base de datos.
  1. Comenzamos por crear un nuevo archivo de texto plano llamado export.sh en el lugar que deseamos y le asignamos los permisos necesarios.
    testsrv:~ # touch export.sh
    testsrv:~ # chmod 755 export.sh
    
  2. Luego procedemos a editar el archivo.
    testsrv:~ # vim export.sh
    
    Y a agregarle el siguiente script bash al mismo:
    #!/bin/bash
     
    # -- DEFINICIÓN VARIABLES DE FECHA Y HORA.
    DIA=`date +"%Y%m%d"`
    HORA=`date +"%H%M"`
     
    # -- CONFIGURACIÓN DE VARIABLES GLOBALES
    DUMP_HOME="."
    DUMP_FILE="dump_"$DIA"_"$HORA".sql"
     
    MYSQL_DBUSER_ADM='root'
    MYSQL_DBNAME="mi_db"
    PG_DBUSER_ADM="postgres"
    PG_DBNAME="mi_db"
     
    # -- SE LIMPIA LA CONSOLA Y SE DESPLIEGA EL TITULO DEL PROGRAMA.
    clear
    echo "EXPORT"
    echo "======"
     
    # -- SE VERIFICA QUE EL USUARIO HAYA PASADO COMO PARAMETRO DE LA APLICACIÓN EL TIPO
    # DE BASE DE DATOS A LA QUE SE TIENE QUE CONECTAR EL SISTEMA (MYSQL O POSTGRESQL)
    if [ -z $1 ]; then
        echo "Error en la ejecución! Faltan parámetros.."
        echo "Ejemplo ejecución:"
        echo
        echo "  $ sh export.sh [mysql|pg]"
        echo
        exit
    fi
     
    # -- SE COMPRUEBA QUE EL PRIMER PARÁMETRO RECIBIDO CORRESPONDA 
    # A LAS OPCIONES VÁLIDAS QUE SON mysql Y pg.
    if [ $1 != "mysql" ] && [ $1 != "pg" ]; then
        echo "Error en la ejecución! las opciones para el primer parámetro pueden ser solamente 'mysql' y 'pg' (postgres)."
        echo "Ejemplo ejecución:"
        echo
        echo "  $ sh export.sh [mysql|pg]"
        echo
        exit
    fi
     
    # -- SE LE SOLICITA AL OPERADOR QUE INGRESE LA CONTRASEÑA DEL USUARIO
    # ADMINISTRADOR DE LA BASE DE DATOS.
    STTY_SAVE=$(stty -g)
    stty -echo
    if [ $1 == "mysql" ]; then
        echo "Favor de introducir a continuación la contraseña del usuario '$MYSQL_DBUSER_ADM', administrador del motor de base de datos 'MySQL'."
    elif [ $1 == "pg" ]; then
        echo "Favor de introducir a continuación la contraseña del usuario '$PG_DBUSER_ADM', administrador del motor de base de datos 'PostgreSQL'."
    else
        echo "Favor de introducir a continuación la contraseña del usuario administrador del motor de base de datos."
    fi
    echo
    echo -n "Introduzca Password:"
    read DBADMIN_SECRET_PASSWD
    stty $STTY_SAVE
    echo
    echo
     
    # -- SEGÚN LA BASE DE DATOS ESPECIFICADA SE PROCEDE A EXPORTAR LA BASE DE DATOS.
    if [ $1 == "mysql" ]; then
        echo "Exportando la base de datos MySQL '$MYSQL_DBNAME' del sistema. Aguarde un momento..."
        mysqldump -v -u $MYSQL_DBUSER_ADM -p$DBADMIN_SECRET_PASSWD --database $MYSQL_DBNAME > $DUMP_HOME/mysql-$DUMP_FILE
        echo "Fin del proceso de exportación! El archivo de exportación generado se encuentra en '$DUMP_HOME/mysql-$DUMP_FILE'."
        echo
    elif [ $1 == "pg" ]; then
        echo "Exportando la base de datos PostgreSQL '$PG_DBNAME' del sistema. Aguarde un momento..."
        export PGUSER=$PG_DBUSER_ADM
        export PGPASSWORD=$DBADMIN_SECRET_PASSWD
        pg_dump -b -F p --column-inserts $PG_DBNAME > $DUMP_HOME/pg-$DUMP_FILE
        unset PGUSER
        unset PGPASSWORD
        echo "Fin del proceso de exportación! El archivo de exportación generado se encuentra en '$DUMP_HOME/pg-$DUMP_FILE'."
    else
        echo "Opción no soportada!"
        echo
    fi
    
    Enlace: Script en Github Gist.

  3. En el nuevo contenido del archivo export.sh tenemos que configurar ciertas variables necesarias para el correcto funcionamiento del script. Las variables son las siguientes:
    • DUMP_HOME: Permite definir el directorio en donde deseamos ubicar el archivo de exportación.
    • DUMP_FILE: Permite especificar el nombre parcial del archivo de exportación, que incluye las variables de fecha y hora para que el archivo lleve esta información en su nombre.
    • MYSQL_DBUSER_ADM: Definición del usuario administrador del motor de base de datos MySQL, que normalmente suele ser el usuario root.
    • MYSQL_DBNAME: Nombre de la base de datos contenida en MySQL, de cuyo esquema deseamos generar el dump o archivo de exportación.
    • PG_DBUSER_ADM: Requiere la definición del nombre del usuario administrador del motor de base de datos, que en el caso de PostgreSQL suele ser el usuario postgres.
    • PG_DBNAME: Nombre de la base de datos contenida en PostgreSQL, de cuyo esquema deseamos generar el archivo de exportación.
    Realizadas las configuraciones anteriores guardamos los cambios y cerramos el archivo para volver al prompt.

  4. Con los pasos anteriores ya hemos terminado de crear y configurar el script, ahora solo resta probarlo. Por ejemplo, si tenemos corriendo el motor de base de datos MySQL y hemos configurado al script la base de datos que deseamos exportar, podemos ejecutar el script de la siguiente manera para generar el archivo de exportación:
    testsrv:~ # sh export.sh mysql
    
    Durante la ejecución se solicitará al usuario operador la contraseña del usuario administrador de MySQL que hemos configurado en la variable MYSQL_DBUSER_ADM. Al finalizar generará un archivo dump llamado mysql-dump_YYYYMMDD_HHMI.sql que contiene las debidas sentencias SQL.

    De igual modo, si tenemos en el mismo host corriendo el motor de base de datos PostgreSQL, cuya base de datos se haya configurado también en el script mediante la variable PG_DBNAME, podemos exportarla de la siguiente manera:
    testsrv:~ # sh export.sh pg
    
    Como ahora le hemos indicado el argumento pg en vez del argumento anterior mysql, el script generará un archivo dump denominado pg-dump_YYYYMMDD_HHMI.sql.


Script de importación

El script que se tratará a continuación permite importar a partir de los archivos dumps generados con el script export.sh tratado más arriba, las base de datos en MySQL o PostgreSQL.
  1. Como primer paso creamos un archivo llamado import.sh y le asignamos los permisos correspondientes.
    testsrv:~ # touch import.sh
    testsrv:~ # chmod 755 import.sh
    
  2. Luego lo editamos.
    testsrv:~ # vim import.sh
    
    Y le agregamos el siguiente contenido:
    #!/bin/bash
     
    # -- CONFIGURACIÓN DE VARIABLES GLOBALES
    APP_HOME="."
    APP_OUTPUT="import.log"
     
    MYSQL_DBUSER_ADM="root"
    MYSQL_DBUSER="admin"
    MYSQL_DBPASS="admin"
    MYSQL_DBNAME="mi_db"
     
    PG_DBUSER_ADM="postgres"
    PG_DBUSER="admin"
    PG_DBPASS="admin"
    PG_DBNAME="mi_db"
     
    # -- SE LIMPIA LA CONSOLA Y SE DESPLIEGA EL TITULO DEL PROGRAMA.
    clear
    echo "IMPORT"
    echo "======"
     
    # -- SE VERIFICA QUE LOS DOS PARAMETROS QUE INDICAN EL TIPO DE BASE 
    # DE DATOS A UTILIZAR (MYSQL O POSTGRESQL) Y EL ARCHIVO DUMP DE DONDE
    # IMPORTAR LA BASE DE DATOS HAYAN SIDO PASADOS POR EL USUARIO.
    if [ -z $1 ] || [ -z $2 ]; then
        echo "Error en la ejecución! Faltan parámetros.."
        echo "Ejemplo ejecución:"
        echo
        echo "  $ sh import.sh [mysql|pg] dump.sql"
        echo
        exit
    fi
     
    # -- SE COMPRUEBA QUE EL PRIMER PARÁMETRO RECIBIDO CORRESPONDA 
    # A LAS OPCIONES VÁLIDAS QUE SON mysql Y pg.
    if [ $1 != "mysql" ] && [ $1 != "pg" ]; then
        echo "Error en la ejecución! las opciones para el primer parámetro pueden ser solamente 'mysql' y 'pg' (postgres)."
        echo "Ejemplo ejecución:"
        echo
        echo "  $ sh import.sh [mysql|pg] dump.sql"
        echo
    exit
    fi
     
    # -- SE VERIFICA LA EXISTENCIA DEL ARCHIVO DUMP.
    if ! [ -f $APP_HOME/$2 ]; then
        echo "Error en la ejecución! El archivo dump '$2' no existe."
        echo
        exit
    fi
     
    # -- SE LE SOLICITA AL OPERADOR QUE INGRESE LA CONTRASEÑA DEL USUARIO
    # ADMINISTRADOR DE LA BASE DE DATOS.
    STTY_SAVE=$(stty -g)
    stty -echo
    if [ $1 == "mysql" ]; then
        echo "Favor de introducir a continuación la contraseña del usuario '$MYSQL_DBUSER_ADM', administrador del motor de base de datos 'MySQL'."
    elif [ $1 == "pg" ]; then
        echo "Favor de introducir a continuación la contraseña del usuario '$PG_DBUSER_ADM', administrador del motor de base de datos 'PostgreSQL'."
    else
        echo "Favor de introducir a continuación la contraseña del usuario administrador del motor de base de datos."
    fi
    echo
    echo -n "Introduzca Password: "
    read DBADMIN_SECRET_PASSWD
    stty $STTY_SAVE
    echo
    echo
     
    # -- SEGÚN LA BASE DE DATOS ESPECIFICADA SE PROCEDE A IMPORTAR EL DUMP.
    echo "" > $APP_HOME/$APP_OUTPUT
    if [ $1 == "mysql" ]; then
        echo -n "Desea eliminar la base de datos $MYSQL_DBNAME y el usuario $MYSQL_DBUSER antes de importar la copia de seguridad? OPCIONES (S|N): "
        read ELIMINA_DB_USER
        if [ $ELIMINA_DB_USER == "S" ] || [ $ELIMINA_DB_USER == "s" ]; then
            echo "Eliminando la base de datos y el usuario del sistema del motor MySQL. Aguarde un momento..."
            mysql -v -u $MYSQL_DBUSER_ADM -p$DBADMIN_SECRET_PASSWD -e "drop database $MYSQL_DBNAME;" >> $APP_HOME/$APP_OUTPUT
            mysql -v -u $MYSQL_DBUSER_ADM -p$DBADMIN_SECRET_PASSWD -e "drop user $MYSQL_DBUSER@localhost;" >> $APP_HOME/$APP_OUTPUT
            echo
        fi
        echo "Importando Base de Datos del sistema en MySQL. Aguarde un momento..."
        mysql -v -u $MYSQL_DBUSER_ADM -p$DBADMIN_SECRET_PASSWD < $APP_HOME/$2 >> $APP_HOME/$APP_OUTPUT
        mysql -v -u $MYSQL_DBUSER_ADM -p$DBADMIN_SECRET_PASSWD -e "grant all on $MYSQL_DBNAME.* to $MYSQL_DBUSER@localhost identified by '$MYSQL_DBPASS'" >> $APP_HOME/$APP_OUTPUT
        echo "Fin del proceso de importación! Puede ver la salida del proceso en el archivo '$APP_HOME/$APP_OUTPUT'."
        echo
    elif [ $1 == "pg" ]; then
        export PGUSER=$PG_DBUSER_ADM
        export PGPASSWORD=$DBADMIN_SECRET_PASSWD
        echo -n "Desea eliminar la base de datos $PG_DBNAME y el usuario $PG_DBUSER antes de importar la copia de seguridad? OPCIONES (S|N): "
        read ELIMINA_DB_USER
        if [ $ELIMINA_DB_USER == "S" ] || [ $ELIMINA_DB_USER == "s" ]; then
            echo "Eliminando la base de datos y el usuario del sistema del motor PostgreSQL. Aguarde un momento..."
            psql -L $APP_HOME/$APP_OUTPUT -c "drop database $PG_DBNAME;" >> $APP_HOME/$APP_OUTPUT
            psql -L $APP_HOME/$APP_OUTPUT -c "drop user $PG_DBUSER;" >> $APP_HOME/$APP_OUTPUT
            echo
        fi
        echo "Importando Base de Datos del sistema en PostgreSQL. Aguarde un momento..."
        psql -L $APP_HOME/$APP_OUTPUT -c "create user $PG_DBUSER createdb createuser createrole;" >> $APP_HOME/$APP_OUTPUT
        psql -L $APP_HOME/$APP_OUTPUT -c "alter user $PG_DBUSER with password '$PG_DBPASS';" >> $APP_HOME/$APP_OUTPUT
        psql -L $APP_HOME/$APP_OUTPUT -c "create database $PG_DBNAME;" >> $APP_HOME/$APP_OUTPUT
        psql -L $APP_HOME/$APP_OUTPUT -c "alter database $PG_DBNAME owner to $PG_DBUSER;" >> $APP_HOME/$APP_OUTPUT
        psql -L $APP_HOME/$APP_OUTPUT -d $PG_DBNAME -f $APP_HOME/$2 >> $APP_HOME/$APP_OUTPUT
        unset PGUSER
        unset PGPASSWORD
        echo "Fin del proceso de importación! Puede ver la salida del proceso en el archivo '$APP_HOME/$APP_OUTPUT'."
        echo
    else
        echo "Opción no soportada!"
        echo
    fi
    
    Enlace: Script en Github Gist.

  3. Al igual que en el archivo export.sh, en el script import.sh también debemos configurar las siguientes variables:
    • APP_HOME: Ruta de trabajo del script, si se lo deja por defecto la ruta de trabajo es en el directorio en donde se ejecuta el script.
    • APP_OUTPUT: Nombre del archivo log en el cual se va a escribir la salida estandar del proceso de importación.
    • MYSQL_DBUSER_ADM: Especificación del usuario administrador de MySQL, que por defecto es el usuario root.
    • MYSQL_DBUSER: Usuario dueño de la base de datos a ser importada.
    • MYSQL_DBPASS: Contraseña del usuario dueño de la base de datos a ser importada.
    • MYSQL_DBNAME: Nombre de la base de datos MySQL a ser importada, y que debe existir en el archivo dump.
    • PG_DBUSER_ADM: Especificación del usuario administrador de PostgreSQL, que por defecto suele ser postgres.
    • PG_DBUSER: Usuario dueño de la base de datos a ser importada.
    • PG_DBPASS: Contraseña del usuario dueño de la base de datos.
    • PG_DBNAME: Nombre de la base de datos PostgreSQL a ser importada a partir del archivo dump.
    Hechas las configuraciones guardamos los cambios y salimos del archivo.

  4. Ahora toca ejecutar el script import.sh y probar importar una base de datos a partir de un archivo dump generado con el script export.sh. A import.sh le tendremos que pasar dos argumentos, el primero el motor de base de datos [mysql|pg] y el segundo el nombre del archivo dump.
    OBS: Si se ha dejado la variable APP_HOME con su configuración por defecto, el archivo dump especificado como argumento deberá estar localizado en el mismo directorio en el cual se ejecuta el script import.sh.
    Para importar una base de datos MySQL el procedimiento sería el siguiente:
    testsrv:~ # sh import.sh mysql mysql-dump_YYYYMMDD_HHMI.sql
    
    De igual manera sería para importar una base de datos en PostgreSQL, con la  diferencia del primer argumento pg y por el nombre del archivo dump, que debe ser correspondiente al motor PostgreSQL:
    testsrv:~ # sh import.sh pg pg-dump_YYYYMMDD_HHMI.sql
    
    En ambos casos, durante el procedimiento se realizarán validaciones de los argumentos especificados, se le solicitará al operador introducir la contraseña del usuario administrador del motor de base de datos seleccionado y se le consultará si desea eliminar la base de datos y el usuario antes de proceder con la importación para las ocasiones en que deseamos reemplazar una base de datos ya existente.

Comentarios

Entradas populares