- Vamos a crear un Bash Script que se conecte localmente a una base de datos DB2 y envié un reporte vía email
Veamos el siguiente escenario: una universidad esta capturando inasistencias por materia de los alumnos de primer año. Por políticas universitarias la tolerancia máxima es de tres faltas y cuatro en algunas materias. El requerimiento podría ser mandar un reporte semanal al asesor con el total de candidatos por materia que están por alcanzar el máximo de faltas hasta el momento.
Empecemos con un ejemplo de una tabla que esta guardando inasistencias de estudiantes por materia:
"ALUMNO_ID" BIGINT NOT NULL GENERATED ALWAYS AS IDENTITY ( ... ... ) "MATERIA" VARCHAR(10000) NOT NULL , "INASISTENCIA" INTEGER NOT NULL , ...
Ejecutar queries en DB2
Primero vamos a crear la función que ejecute SQL queries en la base de datos, los guarde en un archivo de texto y la mandamos llamar con unos cuantos ejemplos:
#!/bin/bash _file="reportCandidates2fail.txt" _db="UNIVERSITY_DB" _table="STUDENTS_ABSENCES" # Funcion para ejecutar sql queries en db2 # necesita dos parametros: SQL ("$1") y MATERIA ("$2") function runQuery(){ query=$(db2 -x "$1") EXIT_CODE=$? if [ $EXIT_CODE -ne 0 ] ; then echo "Error : $query" else echo "$2, $query" >> ${_file} fi } # Connect to the database db2 connect to $_db _SQL="SELECT COUNT(*) FROM ${_table} WHERE MATERIA='MATEMATICAS' AND INASISTENCIA=2" runQuery "${_SQL}" "MATEMATICAS" _SQL2="SELECT COUNT(*) FROM ${_table} WHERE MATERIA='REDES' AND INASISTENCIA=2" runQuery "${_SQL2}" "REDES" _SQL3="SELECT COUNT(*) FROM ${_table} WHERE MATERIA='DEPORTE' AND INASISTENCIA=3" runQuery "${_SQL3}" "DEPORTE" #SQL here #SQL here #And more funny SQL here
Arrays y loops
Para ahorrarnos lineas de código y no tener que estar escribiendo un SQL por por cada materia vamos a hacer unos arreglos y unos ciclos:
#!/bin/bash _file="reportCandidates2fail.txt" _db="UNIVERSITY_DB" _table="STUDENTS_ABSENCES" # Arrays of 3 and 4 absences _4absencesClass=('DEPORTE' 'CULTURA' 'ETICA' ); _3absencesClass=('MATEMATICAS' 'PROGRAMACION' 'BD' 'REDES' 'SO'); # Funcion para ejecutar sql queries en db2 # necesita dos parametros: SQL ("$1") y MATERIA ("$2") function runQuery(){ query=$(db2 -x "$1") EXIT_CODE=$? if [ $EXIT_CODE -ne 0 ] ; then echo "Error : $query" else echo "$2, $query" >> ${_file} fi } # Connect to the database db2 connect to $_db # 4 absences classes for x in "${_4absencesClass[@]}"; do _sql="SELECT COUNT(*) FROM ${_table} WHERE MATERIA=${x} AND INASISTENCIA=3" runQuery "$_sql" "$x" done # 3 absences classes for y in "${_3absencesClass[@]}"; do _sql="SELECT COUNT(*) FROM ${_table} WHERE MATERIA=${y} AND INASISTENCIA=2" runQuery "$_sql" "$y" done
Ahora nomas agregamos la siguiente linea al final del script para mandar el correo, siempre es bueno ponernos en bcc para saber si se mando correctamente:
# mail id _mail="tutor@universidad.com" _mailAdmin="sagara@tecnolack.com" # mail notification cat ${_file} | mail -s "$Candidatos a fallar la materia" -b $_mailAdmin $_mail
Contador
También podemos agregarle un contador, para notificar el numero total de estudiantes en esta situación:
# Counter function to display total of candidates documents function getTotal(){ _total=$(expr $_total + $1) } # to call the counter # getTotal NUMBER
Versión final
El contador lo mandamos llamar cada vez que ejecutemos un query, dentro de la función runQuery lo veo mas practico y fácil. La versión final del código podría ser así ya con unos detalles incluidos, como documentar el script para que alguien que lo vea entienda que hace:
#!/bin/bash # # ################################################ # # Simple bash script to create a report with total # of candidates to fail each class # Usage: sh runReports.sh # Version: 1.0 Date: 20-June-2013 # # Contact: sagara@tecnolack.com # # ################################################ _now=$(date +"%m_%d_%Y") _file="reportCandidates2fail_${_now}.txt" # mail id _mail="tutor@universidad.com" _mailAdmin="sagara@tecnolack.com" _db="UNIVERSITY_DB" _table="STUDENTS_ABSENCES" # Arrays of 3 and 4 absences _4absencesClass=('DEPORTE' 'CULTURA' 'ETICA' ); _3absencesClass=('MATEMATICAS' 'PROGRAMACION' 'BD' 'REDES' 'SO'); # Counter function to display total of candidates function getTotal(){ _total=$(expr $_total + $1) } # Funcion para ejecutar sql queries en db2 # necesita dos parametros: SQL ("$1") y MATERIA ("$2") function runQuery(){ query=$(db2 -x "$1") EXIT_CODE=$? if [ $EXIT_CODE -ne 0 ] ; then echo "Error : $query" else echo "$2, $query" >> ${_file} getTotal "$query" fi } # Header to report file echo "MATERIA, COUNT" > ${_file} # Connect to the database db2 connect to $_db # 4 absences classes for x in "${_4absencesClass[@]}"; do _sql="SELECT COUNT(*) FROM ${_table} WHERE MATERIA=${x} AND INASISTENCIA=3" runQuery "$_sql" "$x" done # 3 absences classes for y in "${_3absencesClass[@]}"; do _sql="SELECT COUNT(*) FROM ${_table} WHERE MATERIA=${y} AND INASISTENCIA=2" runQuery "$_sql" "$y" done # mail notification cat ${_file} | mail -s "${_total} candidatos a fallar la materia" -b $_mailAdmin $_mail
Para terminar agregamos «${_total}» en el subject del correo. No hace falta mencionar que los archivos o logs seguirán siendo almacenados en el directorio actual con la nomenclatura: «reportCandidates2fail_MM_DD_YYYY.txt» (e.g. reportCandidates2fail_06_20_2013.txt).
Le damos permisos de ejecución y lo ejecutamos:
chmod +x runReports.sh sh runReports.sh
Listo. Espero les sea de utilidad.
Documentación | IBM